تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
عندما يفوز تصميم إعلانك بمزاد، يمكن أن تُعلمك Google بالسعر الفائز
إذا كان تصميم الإعلان يتضمّن وحدة الماكرو ${AUCTION_PRICE}.
عند توسيع وحدة الماكرو، يتم عرض السعر الفائز في شكل مُشفَّر. ويمكن تضمينه في تصميم إعلان، على سبيل المثال، من خلال طلب بكسل غير مرئي
يتم عرضه كجزء من الإعلان:
يمكن أيضًا تضمين وحدة الماكرو ${AUCTION_PRICE} في عنوان URL الخاص بتنسيق VAST لتصاميم إعلانات الفيديو، ولكن ليس في عنوان URL لموضع الإعلان في تنسيق VAST:
https://example.com/vast/v?price=${AUCTION_PRICE}
السيناريو
يتضمّن طلب عروض الأسعار في OpenRTB وحدة الماكرو ${AUCTION_PRICE}
في مقتطف HTML أو عنوان URL لملف VAST الذي يعرضه على Google.
تستبدل Google السعر الفائز بالرمز البرمجي في ترميز base64 غير المزوّد ببادئة ومتوافق مع الويب (RFC 3548).
يجتاز المقتطف عملية التأكيد بالتنسيق الذي اخترته. على سبيل المثال، قد يتم تمرير التأكيد في عنوان URL لطلب بكسل غير مرئي
يتم عرضه كجزء من الإعلان.
على الخادم، يفكّر تطبيقك ترميز base64 المتوافق مع الويب لمعلومات السعر الفائز ويفكّ شفرة النتيجة.
التبعيات
ستحتاج إلى مكتبة تشفير متوافقة مع SHA-1 HMAC، مثل
Openssl.
يستخدم نموذج الرمز البرمجي في Java أداة فك ترميز base64 من مشروع Apache
commons. لن تحتاج إلى تنزيل رمز Apache commons،
لأنّ التنفيذ المرجعي يتضمّن الجزء الضروري وبالتالي هو
مكتفٍ ذاتيًا.
يستخدم نموذج الرمز البرمجي بلغة C++ طريقة OpenSSL
base64 BIO. تأخذ هذه الدالة سلسلة مشفّرة بترميز base64 وآمنة على الويب (RFC 3548) وتُفكّ تشفيرها.
عادةً ما تستبدل سلاسل base64 المتوافقة مع الويب البادئة "=" بالبادئة "." (يُرجى العلم أنّه تتم إضافة علامات الاقتباس
لوضوح القراءة ولا يتم تضمينها في بروتوكول
)، ولكن لا يؤدي الاستبدال باستخدام الماكرو إلى إضافة بادئة إلى السعر المشفَّر. يضيف التنفيذ المرجعي
الحشو لأنّ OpenSSL يواجه مشكلة في
السلاسل غير المضمّنة.
الترميز
يتطلب تشفير وفك تشفير الأسعار الفائزة مفتاحَين سريين مشترَكين. مفتاح السلامة ومفتاح التشفير، يُشار إليهما باسم i_key
وe_key على التوالي يتم توفير كلا المفتاحَين عند إعداد الحساب كهاتَين من سلاسل base64 متوافقة مع الويب، ويمكن العثور عليهما في صفحة "المشترون المعتمَدون"
ضمن إعدادات مقدمي عروض الأسعار
> إعدادات عروض الأسعار في الوقت الفعلي > مفاتيح التشفير.
يتم تشفير السعر باستخدام مخطّط تشفير مخصّص مصمّم لمحاولة
تقليل حجم البيانات غير الضرورية مع ضمان أمان كافٍ. يستخدم مخطّط التشفير
خوارزمية HMAC ذات المفتاح لإنشاء لوحة سرية استنادًا إلى معرّف حدث الظهور
الفريد.
يبلغ طول السعر المشفّر 28 بايتًا ثابتًا. ويتألف من
متّجه إعداد مكوّن من 16 بايت و8 بايت من النص المشفَّر وتوقيع
سلامة مكوّن من 4 بايت. يتم ترميز السعر المشفّر باستخدام ترميز base64 الآمن على الويب، وفقًا لمعيار RFC
3548، مع حذف أحرف الحشو. وبالتالي، يتم ترميز السعر المشفَّر الذي يبلغ 28 بايت
كسلسلة base-64 متوافقة مع الويب تتألف من 38 حرفًا بغض النظر عن
السعر الفائز المدفوع.
يتم تشفير السعر على النحو التالي: <price xor HMAC(encryption_key,
initialization_vector)>، لذا يتم احتساب عملية فك التشفير باستخدام
HMAC(encryption_key,initialization_vector) وإجراء عملية XOR مع
السعر المشفَّر لعكس التشفير. تستغرق مرحلة السلامة 4 بايت من
<HMAC(integrity_key, price||initialization_vector)> حيث
|| هي التسلسل.
مدخلات
iv
متّجه الإعداد (16 بايت - فريد لمرّة الظهور)
e_key
مفتاح التشفير (32 بايت - يتم تقديمه عند إعداد الحساب)
i_key
مفتاح السلامة (32 بايت - يتم تقديمه عند إعداد الحساب)
price
(8 بايت - بوحدة الميكرو لعملة الحساب)
الرمز
hmac(k, d)
دالة SHA-1 HMAC للبيانات d باستخدام المفتاح k
a || b
سلسلة a متسلسلة مع سلسلة b
رمز زائف
pad = hmac(e_key, iv) // first 8 bytes
enc_price = pad <xor> price
signature = hmac(i_key, price || iv) // first 4 bytes
final_message = WebSafeBase64Encode( iv || enc_price || signature )
مخطّط فك التشفير
يجب أن يفكّ رمز فك التشفير السعر باستخدام مفتاح التشفير، ويتحقق من صحة أجزاء السلامة باستخدام مفتاح السلامة. سيتم تزويدك بالطُرق أثناء عملية الإعداد. لا تفرض هذه الميزة أي قيود على تفاصيل كيفية
تنظيم عملية التنفيذ. في معظم الأحيان، من المفترض أن تتمكّن من استخدام
نموذج الرمز البرمجي وتعديله وفقًا لاحتياجاتك.
مدخلات
e_key
مفتاح التشفير، 32 بايت، يتم تقديمه عند إعداد الحساب
i_key
مفتاح السلامة، 32 بايت، يتم تقديمه عند إعداد الحساب
final_message
38 حرفًا بترميز base64 متوافق مع الويب
رمز زائف
// Base64 padding characters are omitted.// Add any required base64 padding (= or ==).final_message_valid_base64=AddBase64Padding(final_message)// Web-safe decode, then base64 decode.enc_price=WebSafeBase64Decode(final_message_valid_base64)// Message is decoded but remains encrypted.(iv,p,sig)=enc_price// Split up according to fixed lengths.price_pad=hmac(e_key,iv)price=p<xor>price_padconf_sig=hmac(i_key,price||iv)success=(conf_sig==sig)
رصد هجمات الردود القديمة
لرصد هجمات الردود القديمة أو هجمات إعادة التشغيل، ننصحك بمحاولة
فلترة الردود التي لها طابع زمني يختلف بشكل كبير عن وقت
النظام، بعد مراعاة الاختلافات في المناطق الزمنية.
يحتوي متجه الإعداد على طابع زمني في أوّل 8 بايت. ويمكن قراءة هذا الملف باستخدام الدالة C++ التالية:
تاريخ التعديل الأخير: 2025-09-04 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-09-04 (حسب التوقيت العالمي المتفَّق عليه)"],[[["\u003cp\u003eGoogle can reveal the winning price of an auction if the creative includes either the \u003ccode\u003e${AUCTION_PRICE}\u003c/code\u003e macro for OpenRTB or \u003ccode\u003e%%WINNING_PRICE%%\u003c/code\u003e for the Google RTB protocol.\u003c/p\u003e\n"],["\u003cp\u003eThe winning price, when expanded from the macro, is returned in an encrypted format and can be embedded in elements such as an invisible pixel request or a VAST URL, but not the impression URL.\u003c/p\u003e\n"],["\u003cp\u003eDecrypting the winning price requires both an integrity key (\u003ccode\u003ei_key\u003c/code\u003e) and an encryption key (\u003ccode\u003ee_key\u003c/code\u003e), provided during account setup, and a crypto library that supports SHA-1 HMAC.\u003c/p\u003e\n"],["\u003cp\u003eThe encrypted price consists of a 16-byte initialization vector, 8 bytes of ciphertext, and a 4-byte integrity signature, totaling 28 bytes, which are then encoded into a 38-character web-safe base64 string.\u003c/p\u003e\n"],["\u003cp\u003eTo guard against stale response attacks, it's recommended to filter responses based on the timestamp found in the initialization vector, comparing it against the current system time.\u003c/p\u003e\n"]]],["When a creative wins an auction, Google reveals the winning price via macros. OpenRTB uses `${AUCTION_PRICE}`, while the deprecated Google RTB uses `%%WINNING_PRICE%%`. These macros return an encrypted winning price that can be inserted into a creative's pixel request or a video's VAST URL. The encrypted price, a 38-character web-safe base64 string, is decrypted using provided encryption and integrity keys, alongside SHA-1 HMAC. The encryption includes an initialization vector, ciphertext, and integrity signature. Sample code in Java and C++ are available.\n"],null,["When your creative wins an auction, Google can inform you what the winning\nprice was if the creative includes the `${AUCTION_PRICE}` macro.\n\nWhen the macro is expanded, it returns the winning price in an encrypted\nform. It can be included in a creative, for example, with an invisible pixel\nrequest rendered as part of the ad: \n\n```genshi\n\u003cdiv\u003e\n \u003cscript language='JavaScript1.1' src='https://example.com?creativeID=5837243'/\u003e\n \u003cimg src='https://example.com/t.gif?price=${AUCTION_PRICE}' width='1' height='1'/\u003e\n\u003c/div\u003e\n```\n\nThe `${AUCTION_PRICE}` macro can also be included in the VAST URL of\na video creative, but not in the impression URL in the VAST: \n\n```genshi\nhttps://example.com/vast/v?price=${AUCTION_PRICE}\n```\n\nScenario\n\n1. Your OpenRTB bidding application includes the `${AUCTION_PRICE}` macro in the HTML snippet or VAST URL it returns to Google.\n2. Google substitutes the winning price for the macro in unpadded web-safe base64 encoding ([RFC 3548](//tools.ietf.org/html/rfc3548)).\n3. The snippet passes the confirmation in the format you have chosen. For example, the confirmation might be passed in the URL of an invisible pixel request rendered as part of the ad.\n4. On the server, your application web-safe base64 decodes the winning price information and decrypts the result.\n\nDependencies\n\nYou will need a crypto library that supports SHA-1 HMAC, such as\nOpenssl.\n\nSample code\n\nSample code is provided in Java and C++ and can be downloaded from the [privatedatacommunicationprotocol\nproject](//code.google.com/p/privatedatacommunicationprotocol).\n\n- The Java sample code uses the base64 decoder from the [Apache\n commons project](//commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html). You will not need to download the Apache commons code,\n as the reference implementation includes the necessary part and is therefore\n self-contained.\n\n- The C++ sample code uses the [OpenSSL\n base64 BIO method](//www.openssl.org/docs/man1.1.0/crypto/BIO_f_base64.html). It takes a web-safe base64 encoded string ([RFC 3548](//tools.ietf.org/html/rfc3548)) and decodes it.\n Normally, web-safe base64 strings replace \"=\" padding with \".\" (note that\n quotation marks are added for reading clarity and are not included in the\n protocol) but the macro substitution does not pad the encrypted price. The\n reference implementation adds padding because OpenSSL has trouble with\n unpadded strings.\n\nEncoding\n\nWinning price encryption and decryption requires two secret, but shared,\nkeys. An integrity key, and encryption key, referred to as `i_key`,\nand `e_key` respectively. Both keys are provided at account setup as\nweb-safe base64 strings, and can be found on the Authorized Buyers page\nunder [**Bidder\nsettings \\\u003e RTB settings \\\u003e Encryption keys**](//support.google.com/authorizedbuyers/answer/10858928).\n\nExample integrity and encryption keys: \n\n```scdoc\nskU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o= // Encryption key (e_key)\narO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo= // Integrity key (i_key)\n```\n\nKeys should be web-safe decoded and then base64 decoded by your\napplication: \n\n```scdoc\ne_key = WebSafeBase64Decode('skU7Ax_NL5pPAFyKdkfZjZz2-VhIN8bjj1rVFOaJ_5o=')\ni_key = WebSafeBase64Decode('arO23ykdNqUQ5LEoQ0FVmPkBd7xB5CO89PDZlSjpFxo=')\n```\n\nEncryption scheme\n\nThe price is encrypted using a custom encryption scheme that is designed to\nminimize size overhead while ensuring adequate security. The encryption scheme\nuses a keyed HMAC algorithm to generate a secret pad based on the unique\nimpression event ID.\n\nThe encrypted price has a fixed length of 28 bytes. It is comprised of a\n16-byte initialization vector, 8 bytes of ciphertext, and a 4-byte integrity\nsignature. The encrypted price is web-safe base64-encoded, according to RFC\n3548, with padding characters omitted. Thus, the 28-byte encrypted price is\nencoded as a 38 character web-safe base-64 string irrespective of the winning\nprice paid.\n\nExample encrypted prices: \n\n```scdoc\nYWJjMTIzZGVmNDU2Z2hpN7fhCuPemCce_6msaw // 100 CPI micros\nYWJjMTIzZGVmNDU2Z2hpN7fhCuPemCAWJRxOgA // 1900 CPI micros\nYWJjMTIzZGVmNDU2Z2hpN7fhCuPemC32prpWWw // 2700 CPI micros\n```\n\nThe encrypted format is: \n\n```scdoc\n{initialization_vector (16 bytes)}{encrypted_price (8 bytes)}\n{integrity (4 bytes)}\n```\n\nThe price is encrypted as `\u003cprice xor HMAC(encryption_key,\ninitialization_vector)\u003e` so decryption calculates\n`HMAC(encryption_key,initialization_vector)` and xor's with the\nencrypted price to reverse the encryption. The integrity stage takes 4 bytes of\n`\u003cHMAC(integrity_key, price||initialization_vector)\u003e` where\n`||` is concatenation.\n\n| Inputs ||\n|--------------|-------------------------------------------------------------|\n| `iv` | initialization vector (16 bytes - unique to the impression) |\n| `e_key` | encryption key (32 bytes - provided at account set up) |\n| `i_key` | integrity key (32 bytes - provided at account set up) |\n| `price` | (8 bytes - in micros of account currency) |\n| `hmac(k, d)` | SHA-1 HMAC of data `d`, using key `k` |\n| `a || b` | string `a` concatenated with string `b` |\n| ```scdoc pad = hmac(e_key, iv) // first 8 bytes enc_price = pad \u003cxor\u003e price signature = hmac(i_key, price || iv) // first 4 bytes final_message = WebSafeBase64Encode( iv || enc_price || signature ) ``` ||\n\nDecryption scheme\n\nYour decryption code must decrypt the price using the encryption key, and\nverify the integrity bits with the integrity key. The keys will be provided to\nyou during setup. There aren't any restrictions on the details of how you\nstructure your implementation. For the most part, you should be able to take\nthe sample code and adapt it according to your needs.\n\n| Inputs ||\n|-----------------|-------------------------------------------------------|\n| `e_key` | encryption key, 32 bytes - provided at account set up |\n| `i_key` | integrity key, 32 bytes - provided at account set up |\n| `final_message` | 38 characters web-safe base64 encoded |\n| ```scilab // Base64 padding characters are omitted. // Add any required base64 padding (= or ==). final_message_valid_base64 = AddBase64Padding(final_message) // Web-safe decode, then base64 decode. enc_price = WebSafeBase64Decode(final_message_valid_base64) // Message is decoded but remains encrypted. (iv, p, sig) = enc_price // Split up according to fixed lengths. price_pad = hmac(e_key, iv) price = p \u003cxor\u003e price_pad conf_sig = hmac(i_key, price || iv) success = (conf_sig == sig) ``` ||\n\nDetect stale response attacks\n\nTo detect stale response, or replay, attacks, it's recommended that you\nfilter responses with a timestamp that differs significantly from the system\ntime, after accounting for timezone differences.\n\nThe initialization vector contains a timestamp in the first 8 bytes. It can\nbe read by the following C++ function: \n\n```gdscript\nvoid GetTime(const char* iv, struct timeval* tv) {\n uint32 val;\n memcpy(&val, iv, sizeof(val));\n tv-\u003etv_sec = htonl(val);\n memcpy(&val, iv+sizeof(val), sizeof(val));\n tv-\u003etv_usec = htonl(val)\n}\n```\n\nThe timestamp can be converted to a human readable form using the following\nC++ code: \n\n```css+lasso\nstruct tm tm;\nlocaltime_r(&tv-\u003etv_sec, &tm);\n\nprintf(\"%04d-%02d-%02d|%02d:%02d:%02d.%06ld\",\n tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,\n tm.tm_hour, tm.tm_min, tm.tm_sec,\n tv_.tv_usec);\n```\n\nJava library\n\nInstead of implementing the crypto algorithms to encode and decode\nthe winning price, you can use\n[DoubleClickCrypto.java](//github.com/google/openrtb-doubleclick/blob/master/doubleclick-core/src/main/java/com/google/doubleclick/crypto/DoubleClickCrypto.java). For more information, see\n[Cryptography](//github.com/google/openrtb-doubleclick/wiki#cryptography)."]]