Work through this guide to get familiar with the process of sending events with the Data Manager API.
Use the Data Manager API for either of the following scenarios:
Send Google Ads tag conversions or any Google Analytics events with a transaction ID as an additional data source for your tag or Google Analytics for Firebase (GA4F) events, to maximize ad interaction signals and strengthen your data and overall performance.
This feature is available to all Google Ads accounts, but is only available to Google Analytics properties on an allowlist. Fill out the form if you're interested in adding your Google Analytics property to the allowlist.
Send event data for Google Ads offline conversions or enhanced conversions for leads .
Google Ads স্টোরের বিক্রয় রূপান্তর ডেটা পাঠান। এই ফিচারটি শুধুমাত্র অনুমোদিত তালিকায় থাকা Google Ads অ্যাকাউন্টগুলোর জন্য উপলব্ধ।
Send recommended and custom events to Google Analytics.
Send Floodlight offline conversions for Google Marketing Platform products, including Campaign Manager 360 , Search Ads 360 , and Display & Video 360 .
In this guide, you complete the following steps:
- Prepare a
Destinationto receive event data. - Prepare event data to send.
- Build an
IngestionServicerequest for events. - Send the request with the Google APIs Explorer.
- Understand success and failure responses.
Prepare destinations
Before you can send data, you need to prepare at least one Destination for the data. Here are the fields of a Destination . Check out Configure destinations for more details and examples of destinations for different scenarios.
Select the tab that corresponds to your use case.
- Select Advertiser if you're using credentials for a Google Account that is a user in the advertiser accounts you want to manage.
- Select Data Partner if you're using credentials for a Google Account that is a user in a data partner account, and you want to manage advertiser accounts that have a partner link to the data partner account.
বিজ্ঞাপনদাতা
-
operatingAccount The account that receives the events.
For events sent as an additional data source, the operating account can be either a Google Ads account or a Google Analytics property.
যদি
accountTypeটিGOOGLE_ANALYTICS_PROPERTYহয়, তাহলে অনুরোধের ক্রেডেনশিয়াল অবশ্যই এমন একজন গুগল অ্যানালিটিক্স ব্যবহারকারীর হতে হবে, যার ওই প্রপার্টির জন্য Editor বা Administrator ভূমিকা রয়েছে।For Google Ads offline conversions, enhanced conversions for leads, store sales conversions, and conversions with cart data, the operating account must be a Google Ads account.
For Google Marketing Platform conversions, the operating account must be a Floodlight configuration.
-
loginAccount The account where the Google Account for the credentials is a user.
-
productDestinationId The ID of the entity in the
operatingAccountthat receives the events.For events sent as an additional data source, the
productDestinationIdmust be one of the following:The ID of a Google Ads conversion with
typeset toWEBPAGE. In the Google Ads UI, the Conversion source for aWEBPAGEconversion action is Website .The measurement ID of a Google Analytics web data stream.
The Firebase App ID of a Google Analytics iOS or Android app data stream.
For other events sent to Google Analytics, the
productDestinationIdmust be one of the following:The measurement ID of a Google Analytics web data stream.
The Firebase App ID of a Google Analytics iOS or Android app data stream.
For Google Ads offline conversions or enhanced conversions for leads, the
productDestinationIdmust be the ID of a Google Ads conversion action withtypeset toUPLOAD_CLICKS. In the Google Ads UI, the Conversion source for anUPLOAD_CLICKSconversion action is Website (Import from clicks) .For store sales conversions, the
productDestinationIdmust be the ID of a Google Ads conversion action withtypeset toSTORE_SALES. In the Google Ads UI, the Conversion source for aSTORE_SALESconversion action is Store sales .For Floodlight offline conversions, set
productDestinationIdto the Floodlight activity ID .
{
"operatingAccount": {
"accountType": "OPERATING_ACCOUNT_TYPE",
"accountId": "OPERATING_ACCOUNT_ID"
},
"loginAccount": {
"accountType": "LOGIN_ACCOUNT_TYPE",
"accountId": "LOGIN_ACCOUNT_ID"
},
"productDestinationId": "PRODUCT_DESTINATION_ID"
}
Data Partner
-
operatingAccount - The account that receives the events. Must be a Google Ads account. The Data Manager API doesn't support sending events to a Google Analytics property or Floodlight configuration using a linked data partner.
-
loginAccount The account where the credential's user has access.
Set the
accountIdto your Data Partner account ID, and set theaccountTypetoDATA_PARTNER.-
linkedAccount প্রতিষ্ঠিত অংশীদার লিঙ্কযুক্ত অ্যাকাউন্ট, যার মাধ্যমে ক্রেডেনশিয়ালের ব্যবহারকারী
operatingAccountপ্রবেশাধিকার পায়।If a parent of the
operatingAccountis linked to your data partner account, set thelinkedAccountto the parent of theoperatingAccount. If theoperatingAccountis directly linked to your data partner account, don't setlinkedAccount.-
productDestinationId operatingAccountঅন্তর্গত যে সত্তাটি ইভেন্টগুলো গ্রহণ করে, তার আইডি।For events sent as an additional data source using a linked data partner, the
productDestinationIdmust be the ID of a Google Ads conversion withtypeset toWEBPAGE. In the Google Ads UI, the Conversion source for aWEBPAGEconversion action is Website .For Google Ads offline conversions or enhanced conversions for leads, the
productDestinationIdmust be the ID of a Google Ads conversion action withtypeset toUPLOAD_CLICKS. In the Google Ads UI, the Conversion source for anUPLOAD_CLICKSconversion action is Website (Import from clicks) .For store sales conversions, the
productDestinationIdmust be the ID of a Google Ads conversion action withtypeset toSTORE_SALES. In the Google Ads UI, the Conversion source for aSTORE_SALESconversion action is Store sales .
{
"operatingAccount": {
"accountType": "OPERATING_ACCOUNT_TYPE",
"accountId": "OPERATING_ACCOUNT_ID"
},
"loginAccount": {
"accountType": "DATA_PARTNER",
"accountId": "DATA_PARTNER_ACCOUNT_ID"
},
"linkedAccount": {
"accountType": "LINKED_ACCOUNT_TYPE",
"accountId": "LINKED_ACCOUNT_ID"
},
"productDestinationId": "PRODUCT_DESTINATION_ID"
}
The example in this guide shows how to construct a request that sends every event to the same destination. If you want to send events for multiple destinations in the same request, see send events for multiple destinations .
Prepare event data
নিম্নলিখিত ইভেন্ট ডেটা বিবেচনা করুন। প্রতিটি টেবিল একটি রূপান্তর ইভেন্টের সাথে সম্পর্কিত। প্রতিটি রূপান্তর ইভেন্টে ইভেন্টের টাইমস্ট্যাম্প, এর রূপান্তর অ্যাকশন এবং রূপান্তর মান রয়েছে।
প্রতিটি ইভেন্টে বিজ্ঞাপন শনাক্তকারী (ad identifiers), যেমন gclid , অথবা ব্যবহারকারী শনাক্তকারী (user identifiers), যেমন ইমেল ঠিকানা, ফোন নম্বর এবং ঠিকানার তথ্য থাকতে পারে। একটি ইভেন্টে আরও থাকতে পারে:
- Information about the user assessed at the time of the event , like the value of the customer or whether they are a new, returning, or reengaged customer.
- শপিং কার্টের তথ্য ।
- Additional event parameters or user properties for a destination, such as
clientId,appInstanceIdoruserIdfor Google Analytics.
Here's the event data:
Event 1
| Event #1 | |
|---|---|
conversion_time | 2025-06-10 15:07:01-05:00 |
conversion_action_id | 123456789 |
transaction_id | ABC798654321 |
conversion_value | 30.03 |
currency | USD |
gclid | GCLID_1 |
emails | |
given_name | John |
family_name | Smith-Jones |
region_code | us |
postal_code | 94045 |
customer_type | NEW |
customer_value_bucket | HIGH |
client_id | 1234567890.1761581763 |
user_id | user_ABC12345 |
ad_unit_name | Banner_01 |
event_name | purchase |
| কার্টের আইটেমগুলি | |
item_id | SKU_12345 |
item_name | Stan and Friends Tee |
item_affiliation | Google Merchandise Store |
item_coupon | SUMMER_FUN |
item_discount | 2.22 |
item_index | 0 |
item_brand | Google |
item_category | Apparel |
item_category2 | Adult |
item_category3 | Shirts |
item_category4 | Crew |
item_category5 | Short sleeve |
item_list_id | related_products |
item_list_name | Related Products |
item_price | 10.01 |
item_quantity | 3 |
Event 2
| Event #2 | |
|---|---|
conversion_time | June 10, 2025 11:42:33PM America/New_York |
conversion_action_id | 123456789 |
transaction_id | DEF999911111 |
conversion_value | 42.02 |
currency | eur |
gclid | GCLID_2 |
emails | |
given_name | zoë |
family_name | pérez |
region_code | PT |
postal_code | 1229-076 |
customer_type | RETURNING |
client_id | 9876543210.1761582117 |
user_id | user_DEF9876 |
ad_unit_name | Banner_02 |
event_name | purchase |
| কার্টের আইটেমগুলি | |
item_id | SKU_12346 |
item_name | Google Grey Women's Tee |
item_affiliation | Google Merchandise Store |
item_coupon | SUMMER_FUN |
item_discount | 3.33 |
item_index | 1 |
item_brand | Google |
item_category | Apparel |
item_category2 | Adult |
item_category3 | Shirts |
item_category4 | Crew |
item_category5 | Short sleeve |
item_list_id | related_products |
item_list_name | Related Products |
item_price | 21.01 |
item_quantity | 2 |
ঘটনা ৩
| Event #3 (Store sales) | |
|---|---|
conversion_time | June 11, 2025 12:05:00PM America/New_York |
conversion_action_id | 123456789 |
transaction_id | XYZ987654321 |
conversion_value | 450.0 |
currency | usd |
given_name | Charlie |
family_name | Smith-Jones |
region_code | US |
postal_code | 10011 |
store_id | STORE_NY_001 |
merchant_id | 123 |
merchant_feed_label | US |
merchant_feed_language_code | en |
| কার্টের আইটেমগুলি | |
merchant_product_id | ITEM_SKU_987 |
item_quantity | 1 |
item_price | 450.0 |
variable | DEPARTMENT |
value | ELECTRONICS |
Format the data
ফরম্যাটিং গাইডে উল্লেখিত নির্দেশনা অনুযায়ী ফিল্ডগুলো ফরম্যাট করুন। ফরম্যাট করার পর ইভেন্টের ডেটা নিচে দেওয়া হলো:
Event 1
| ইভেন্ট #১ | |
|---|---|
conversion_time | 2025-06-10T15:07:01-05:00 |
conversion_action_id | 123456789 |
transaction_id | ABC798654321 |
conversion_value | 30.03 |
currency | USD |
gclid | GCLID_1 |
emails | |
given_name | john |
family_name | smith-jones |
region_code | US |
postal_code | 94045 |
customer_type | NEW |
customer_value_bucket | HIGH |
client_id | 1234567890.1761581763 |
user_id | user_ABC12345 |
ad_unit_name | Banner_01 |
event_name | purchase |
| কার্টের আইটেমগুলি | |
item_id | SKU_12345 |
item_name | Stan and Friends Tee |
item_affiliation | Google Merchandise Store |
item_coupon | SUMMER_FUN |
item_discount | 2.22 |
item_index | 0 |
item_brand | Google |
item_category | Apparel |
item_category2 | Adult |
item_category3 | Shirts |
item_category4 | Crew |
item_category5 | Short sleeve |
item_list_id | related_products |
item_list_name | Related Products |
item_price | 10.01 |
item_quantity | 3 |
Event 2
| Event #2 | |
|---|---|
conversion_time | 2025-06-10T23:42:33-05:00 |
conversion_action_id | 123456789 |
transaction_id | DEF999911111 |
conversion_value | 42.02 |
currency | EUR |
gclid | GCLID_2 |
emails | |
given_name | zoë |
family_name | pérez |
region_code | PT |
postal_code | 1229-076 |
customer_type | RETURNING |
client_id | 9876543210.1761582117 |
user_id | user_DEF9876 |
ad_unit_name | Banner_02 |
event_name | purchase |
| কার্টের আইটেমগুলি | |
item_id | SKU_12346 |
item_name | Google Grey Women's Tee |
item_affiliation | Google Merchandise Store |
item_coupon | SUMMER_FUN |
item_discount | 3.33 |
item_index | 1 |
item_brand | Google |
item_category | Apparel |
item_category2 | Adult |
item_category3 | Shirts |
item_category4 | Crew |
item_category5 | Short sleeve |
item_list_id | related_products |
item_list_name | Related Products |
item_price | 21.01 |
item_quantity | 2 |
Event 3
| Event #3 (Store sales) | |
|---|---|
conversion_time | 2025-06-11T12:05:00-04:00 |
conversion_action_id | 123456789 |
transaction_id | XYZ987654321 |
conversion_value | 450.0 |
currency | USD |
given_name | charlie |
family_name | smith-jones |
region_code | US |
postal_code | 10011 |
store_id | STORE_NY_001 |
merchant_id | 123 |
merchant_feed_label | US |
merchant_feed_language_code | en |
| কার্টের আইটেমগুলি | |
merchant_product_id | ITEM_SKU_987 |
item_quantity | 1 |
item_price | 450.0 |
variable | DEPARTMENT |
value | ELECTRONICS |
Hash and encode the data
In addition, the formatted email addresses, given names, and family names must be hashed using the SHA-256 algorithm and encoded using either hex or Base64 encoding. Here's the event data after formatting, hashing, and encoding using hex encoding:
Event 1
| ইভেন্ট #১ | |
|---|---|
conversion_time | 2025-06-10T15:07:01-05:00 |
conversion_action_id | 123456789 |
transaction_id | ABC798654321 |
conversion_value | 30.03 |
currency | USD |
gclid | GCLID_1 |
emails | |
given_name | 96D9632F363564CC3032521409CF22A852F2032EEC099ED5967C0D000CEC607A |
family_name | DB98D2607EFFFA28AFF66975868BF54C075ECA7157E35064DCE08E20B85B1081 |
region_code | US |
postal_code | 94045 |
customer_type | NEW |
customer_value_bucket | HIGH |
client_id | 1234567890.1761581763 |
user_id | user_ABC12345 |
ad_unit_name | Banner_01 |
event_name | purchase |
| কার্টের আইটেমগুলি | |
item_id | SKU_12345 |
item_name | Stan and Friends Tee |
item_affiliation | Google Merchandise Store |
item_coupon | SUMMER_FUN |
item_discount | 2.22 |
item_index | 0 |
item_brand | Google |
item_category | Apparel |
item_category2 | Adult |
item_category3 | Shirts |
item_category4 | Crew |
item_category5 | Short sleeve |
item_list_id | related_products |
item_list_name | Related Products |
item_price | 10.01 |
item_quantity | 3 |
Event 2
| Event #2 | |
|---|---|
conversion_time | 2025-06-10T23:42:33-05:00 |
conversion_action_id | 123456789 |
transaction_id | DEF999911111 |
conversion_value | 42.02 |
currency | EUR |
gclid | GCLID_2 |
emails | |
given_name | 2752B88686847FA5C86F47B94CE652B7B3F22A91C37617D451A4DB9AFA431450 |
family_name | 6654977D57DDDD3C0329CA741B109EF6CD6430BEDD00008AAD213DF25683D77F |
region_code | PT |
postal_code | 1229-076 |
customer_type | RETURNING |
client_id | 9876543210.1761582117 |
user_id | user_DEF9876 |
ad_unit_name | Banner_02 |
event_name | purchase |
| কার্টের আইটেমগুলি | |
item_id | SKU_12346 |
item_name | Google Grey Women's Tee |
item_affiliation | Google Merchandise Store |
item_coupon | SUMMER_FUN |
item_discount | 3.33 |
item_index | 1 |
item_brand | Google |
item_category | Apparel |
item_category2 | Adult |
item_category3 | Shirts |
item_category4 | Crew |
item_category5 | Short sleeve |
item_list_id | related_products |
item_list_name | Related Products |
item_price | 21.01 |
item_quantity | 2 |
Event 3
| Event #3 (Store sales) | |
|---|---|
conversion_time | 2025-06-11T12:05:00-04:00 |
conversion_action_id | 123456789 |
transaction_id | XYZ987654321 |
conversion_value | 450.0 |
currency | USD |
given_name | B9DD960C1753459A78115D3CB845A57D924B6877E805B08BD01086CCDF34433C |
family_name | DB98D2607EFFFA28AFF66975868BF54C075ECA7157E35064DCE08E20B85B1081 |
region_code | US |
postal_code | 10011 |
store_id | STORE_NY_001 |
merchant_id | 123 |
merchant_feed_label | US |
merchant_feed_language_code | en |
| কার্টের আইটেমগুলি | |
merchant_product_id | ITEM_SKU_987 |
item_quantity | 1 |
item_price | 450.0 |
variable | DEPARTMENT |
value | ELECTRONICS |
ডেটাগুলোকে Event অবজেক্টে রূপান্তর করুন
প্রতিটি ইভেন্টের ফরম্যাট করা এবং হ্যাশ করা ডেটাকে একটি Event রূপান্তর করুন। নির্দেশ অনুযায়ী নিম্নলিখিত ফিল্ডগুলি পূরণ করুন:
ইভেন্টটি ঘটার সময়ে
eventTimestampসেট করুন।গুগল অ্যানালিটিক্সের জন্য ইভেন্টগুলোতে অবশ্যই গত ৭২ ঘণ্টার মধ্যেকার একটি
eventTimestampথাকতে হবে।আপনার Google Ads, Google Analytics, বা Floodlight ব্যবহারের জন্য প্রয়োজনীয় ফিল্ডগুলো সেট করুন।
গুগল বিজ্ঞাপন
ব্যবহারের ক্ষেত্র শনাক্তকারী transactionIdeventSourceলিডের জন্য গুগল অ্যাডস অফলাইন কনভার্সন বা উন্নত কনভার্সন Required . Set at least one of the following: -
adIdentifiersযেখানেgclid,gbraidবাwbraidএর মধ্যে অন্তত একটি, অথবাlandingPageDeviceInfo.ipAddressসেট করা আছে। - সেশনের বৈশিষ্ট্য
-
userData -
eventDeviceInfo.ipAddress
ঐচ্ছিক আবশ্যক । EventSourceজন্য enum মানগুলির মধ্যে একটিতে সেট করুন।অতিরিক্ত ডেটা উৎস হিসেবে পাঠানো ইভেন্টসমূহ আবশ্যক । নিম্নলিখিতগুলির মধ্যে অন্তত একটি সেট করুন: -
adIdentifiersযেখানেgclid,gbraidবাwbraidএর মধ্যে অন্তত একটি, অথবাlandingPageDeviceInfo.ipAddressসেট করা আছে। - সেশনের বৈশিষ্ট্য
-
userData -
eventDeviceInfo.ipAddress
প্রয়োজনীয় Optional. If set, must be WEB.Store sales conversions - আবশ্যক ।
Eventনিম্নলিখিত ক্ষেত্রগুলি সেট করুন:-
eventLocation.storeId -
currency -
conversionValue
-
- আবশ্যক । ব্যবহারকারী শনাক্তকারী প্রদানের জন্য নিম্নলিখিত ক্ষেত্রগুলি পূরণ করুন:
- Populate
thirdPartyUserDataif the user identifier(s) are from a third-party source. SettingthirdPartyUserDatais only allowed if the login account of theDestinationis a data partner (loginAccount.accountTypeisDATA_PARTNER). - Otherwise, populate
userData.
- Populate
প্রয়োজনীয় আবশ্যক । IN_STOREএ সেট করুন।গুগল অ্যানালিটিক্স
ব্যবহারের ক্ষেত্র শনাক্তকারী transactionIdeventSourceওয়েব ডেটা স্ট্রিমে অতিরিক্ত ডেটা উৎস হিসেবে পাঠানো ইভেন্টসমূহ আবশ্যক । নিম্নলিখিতগুলির মধ্যে অন্তত একটি সেট করুন: -
clientId -
gclidসেট সহadIdentifiers -
userId
প্রয়োজনীয় ঐচ্ছিক। সেট করা হলে, তা অবশ্যই WEBহতে হবে।অ্যাপ ডেটা স্ট্রিমে অতিরিক্ত ডেটা উৎস হিসেবে ইভেন্ট পাঠানো হয়। আবশ্যক ।
appInstanceIdসেট করুন।পরিমাপকে আরও উন্নত করতে
userIdএবংadIdentifiersমতো ঐচ্ছিক ফিল্ডগুলোকেgbraidবাgclidদিয়ে সেট করুন।প্রয়োজনীয় ঐচ্ছিক। সেট করা হলে, তা অবশ্যই APPহতে হবে।ওয়েব ডেটা স্ট্রিমে পাঠানো অন্যান্য ইভেন্ট আবশ্যক । clientIdসেট করুন।purchaseএবংrefundমতো কিছু ইভেন্টের জন্য এটি প্রয়োজন । বিস্তারিত জানতে নির্দিষ্ট ইভেন্টের প্রয়োজনীয়তাগুলো দেখে নিন।ঐচ্ছিক। সেট করা হলে, তা অবশ্যই WEBহতে হবে।অ্যাপ ডেটা স্ট্রিমে পাঠানো অন্যান্য ইভেন্ট আবশ্যক । appInstanceIdসেট করুন।purchaseএবংrefundমতো কিছু ইভেন্টের জন্য এটি প্রয়োজন । বিস্তারিত জানতে নির্দিষ্ট ইভেন্টের প্রয়োজনীয়তাগুলো দেখে নিন।ঐচ্ছিক। সেট করা হলে, তা অবশ্যই APPহতে হবে।ফ্লাডলাইট
ব্যবহারের ক্ষেত্র শনাক্তকারী transactionIdeventSourceঅফলাইন রূপান্তর আবশ্যক।
adIdentifiersহিসেবেgclid,matchId,dclid,impressionId,mobileDeviceId, অথবাencryptedUserIdsমধ্যে অন্তত একটি ব্যবহার করুন।ব্যবহারকারী শনাক্তকারী প্রদান করতে
userDataসেট করুন।ঐচ্ছিক ঐচ্ছিক -
আপনি যদি অতিরিক্ত ডেটা উৎস হিসেবে ইভেন্ট পাঠান, তাহলে গুগল কীভাবে অতিরিক্ত ডেটা উৎসের ডেটা পরিচালনা করে তা পর্যালোচনা করুন।
আপনি যদি গুগল অ্যানালিটিক্সে ইভেন্ট পাঠান, তাহলে ইভেন্টগুলোতে গুগল অ্যানালিটিক্সের তথ্য যোগ করুন ।
If you're sending Google Ads conversions with cart data, Google Analytics recommended events such as
purchasethat require anitemslist, or you want to include cart information with Google Ads store sales conversions or Floodlight conversions, add cart data to the events.ইভেন্টের জন্য আপনার কাছে মান থাকলে অন্য যেকোনো ফিল্ড পূরণ করুন। উপলব্ধ ফিল্ডগুলির সম্পূর্ণ তালিকার জন্য
Eventরেফারেন্স ডকুমেন্টেশন দেখুন।
গুগল কীভাবে অতিরিক্ত ডেটা উৎসের ডেটা পরিচালনা করে
গুগল বিজ্ঞাপন
Within the same conversion action, Google Ads uses the transactionId to deduplicate conversion events sent from different sources (like your website tag and Data Manager API ingestion requests). The following table explains how the data from your ingestion requests is processed.
| দৃশ্যকল্প | ডেটা ক্ষেত্র | How it's handled |
|---|---|---|
transactionId আইডি একটি বিদ্যমান ট্যাগ ইভেন্টের সাথে মেলে | conversionValue (with currencyCode ) | আপডেট করা হয়েছে। দ্রষ্টব্য: কোনো কনভার্সন অ্যাকশনের প্রাথমিক ১৪-দিনের ট্রায়াল পিরিয়ড চলাকালীন, ভ্যালু আপডেট নিষ্ক্রিয় থাকে। ট্রায়াল পিরিয়ড শেষ না হওয়া পর্যন্ত Google Ads রিপোর্টিং-এ ট্যাগটির ভ্যালু ওভাররাইড করা হবে না। |
transactionId আইডি একটি বিদ্যমান ট্যাগ ইভেন্টের সাথে মেলে | conversionValue বা currencyCode ছাড়া অন্যান্য ফিল্ড (উদাহরণস্বরূপ, adIdentifiers.gclid ) | উপেক্ষা করা হয়েছে। আপনার অতিরিক্ত ডেটা উৎসের অন্যান্য ফিল্ড ভ্যালুগুলো, মিলে যাওয়া লেনদেনগুলোর জন্য আপনার গুগল ট্যাগ দ্বারা প্রাথমিকভাবে রেকর্ড করা ফিল্ড ভ্যালুগুলোকে ওভাররাইট করবে না। |
transactionId বিদ্যমান কোনো ইভেন্টের সাথে মেলে না। | প্রদত্ত সকল ডেটা (উদাহরণস্বরূপ, userData , conversionValue , currencyCode ) | একটি নতুন কনভার্সন ইভেন্ট তৈরি করতে ব্যবহৃত হয়। এরপর গুগল আপনার দেওয়া আইডেন্টিফায়ারগুলো (যেমন Note: During the initial 14-day trial period, these newly created conversions will appear in your reporting but won't be used for bidding. After the trial ends, they will automatically become biddable. |
গুগল অ্যানালিটিক্স
Within the same event and property, Google Analytics uses transactionId to deduplicate the event from different sources (like your website tag and Data Manager API ingestion requests). Google Analytics uses the information from the first instance of the same event that it received.
সেশন অ্যাট্রিবিউট যোগ করুন
If you're sending offline conversions or enhanced conversions for leads, add session attributes when other ad identifiers such as a GCLID or WBRAID aren't available. You can also include session attributes in addition to other ad identifiers.
সেশন অ্যাট্রিবিউটগুলো আপনার ওয়েবসাইটের সাথে ব্যবহারকারীর মিথস্ক্রিয়া সম্পর্কে আরও প্রাসঙ্গিক তথ্য ও সংকেত প্রদান করে, যা কনভার্সন পরিমাপ, রিপোর্টিং এবং বিডিংয়ের নির্ভুলতা বাড়াতে পারে।
ডেটা ম্যানেজার এপিআই-তে, সেশন অ্যাট্রিবিউট পাঠানোর জন্য আপনি দুটি পদ্ধতি ব্যবহার করতে পারেন:
Recommended: Set the
sessionAttributesfield ofadIdentifiersto the base64 encoded session attributes string. Follow the instructions in How to capture session_attributes to modify your form submission pages to capture the encoded string.যদি আপনি জাভাস্ক্রিপ্ট ব্যবহার করতে না পারেন, তাহলে স্বতন্ত্র সেশন অ্যাট্রিবিউট ফিল্ডগুলো ক্যাপচার করুন এবং প্রত্যেকটিকে
experimentalFieldsতালিকায় একটি পৃথকExperimentalFieldহিসেবে যুক্ত করুন:-
gad_campaignid -
session_start_time_usec -
gad_source -
landing_page_url -
landing_page_referrer
আপনার যদি
landing_page_user_agentসেশন অ্যাট্রিবিউটের জন্য কোনো ভ্যালু থাকে, তাহলে সেটিadIdentifiers.landingPageDeviceInfoএরuserAgentফিল্ডে পাঠান।স্বতন্ত্র কী-ভ্যালু পেয়ার পাঠানোর ক্ষেত্রে সেরা পদ্ধতিগুলো নিচে দেওয়া হলো:
- ধারাবাহিকভাবে
gad_campaignidএবংsession_start_time_usecপাঠান। সঠিক অ্যাট্রিবিউশনের জন্য এই ফিল্ডগুলো অত্যন্ত গুরুত্বপূর্ণ। - Don't provide an inaccurate or partial
landing_page_urlvalue such as a placeholder string, an internal application path, or an incomplete URL. Omit thelanding_page_urlif you don't have the accurate, full URL.
এখানে একটি নমুনা ইভেন্টের অংশবিশেষ দেওয়া হলো, যেখানে
experimentalFieldsএgad_campaignidওsession_start_time_usecএবংlandingPageDeviceInfoফিল্ডে ইউজার এজেন্ট-এর এন্ট্রি রয়েছে:{ ..., "experimentalFields": [ { "field": "gad_campaignid", "value": "21288051566" }, { "field": "session_start_time_usec", "value": "1767711548052000" } ], "adIdentifiers": { "landingPageDeviceInfo": { "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36" } } }-
Add encrypted user IDs
আপনি যদি ফ্ল্যাডলাইটে কনভার্সন পাঠান, তাহলে এনক্রিপ্টেড ইউজার আইডি ব্যবহার করে ব্যবহারকারীদের শনাক্ত করতে পারেন। আপনি যদি এনক্রিপ্টেড ইউজার আইডি ব্যবহার করেন, তবে সেগুলি কীভাবে এনক্রিপ্ট করা হয়েছে সে সম্পর্কেও আপনাকে বিস্তারিত তথ্য দিতে হবে।
ইভেন্টের জন্য adIdentifiers এর encryptedUserIds তালিকায় একটি EncryptedUserId অবজেক্ট যোগ করুন।
নিম্নলিখিত ক্ষেত্রগুলি আবশ্যক:
-
encryptedId - আবশ্যক । এনক্রিপ্টেড ইউজার আইডি।
-
source - আবশ্যক । এনক্রিপ্টেড ইউজার আইডির উৎস।
%mম্যাচ ম্যাক্রো থেকে প্রাপ্ত আইডির জন্য বৈধ মান হলোAD_SERVING, এবং ডেটা ট্রান্সফার ফাইল থেকে প্রাপ্ত আইডির জন্য বৈধ মান হলোDATA_TRANSFER। -
entityId - Required . The ID of the entity used to encrypt the user ID. This is typically a Campaign Manager 360 account ID if the source is
DATA_TRANSFER, or a Campaign Manager 360 advertiser ID if the source isAD_SERVING. -
entityType - আবশ্যক । ইউজার আইডি এনক্রিপ্ট করতে ব্যবহৃত এনটিটির ধরণ, যা একটি
EncryptionEntityTypeenum ভ্যালু হিসেবে নির্দিষ্ট করা থাকে।
গুগল অ্যানালিটিক্স তথ্য যোগ করুন
অতিরিক্ত ডেটা উৎস হিসেবে পাঠানো কোনো ইভেন্টের গন্তব্যে যদি গুগল অ্যানালিটিক্স প্রপার্টি অন্তর্ভুক্ত থাকে, তাহলে নির্দেশ অনুযায়ী নিম্নলিখিত ফিল্ডগুলি পূরণ করুন:
-
eventName আবশ্যক । গুগল অ্যানালিটিক্স ইভেন্টের নাম।
ইভেন্টের নামটি যদি একটি সংরক্ষিত নাম হয়, তাহলে ডেটা ম্যানেজার এপিআই
INVALID_EVENT_NAMEত্রুটি দেখিয়ে ইভেন্টটি প্রত্যাখ্যান করে।-
transactionId ইভেন্টটির জন্য গুগল অ্যানালিটিক্স ইভেন্ট স্পেসিফিকেশনে নির্দেশিত থাকলে এটি আবশ্যক ।
- শনাক্তকারী
প্রতিটি ধরণের ডেটা স্ট্রিমের জন্য শনাক্তকারীর প্রয়োজনীয়তাগুলো নিচে দেওয়া হলো:
Web data stream
অতিরিক্ত ডেটা উৎস হিসেবে ট্রানজ্যাকশন আইডি সহ কোনো ইভেন্ট পাঠানোর ক্ষেত্রে নিম্নলিখিত ফিল্ডগুলির মধ্যে অন্তত একটি অবশ্যই সেট করতে হবে:
clientId: ওয়েব ক্লায়েন্টের কোনো ব্যবহারকারী ইনস্ট্যান্সের অনন্য শনাক্তকারী। গুগল অ্যানালিটিক্স মেজারমেন্ট প্রোটোকল নির্দেশাবলী দেখুন।userId: একজন ব্যবহারকারীর জন্য একটি অনন্য শনাক্তকারী। আরও তথ্যের জন্য ‘ইউজার-আইডি ব্যবহার করে বিভিন্ন প্ল্যাটফর্মে কার্যকলাপ পরিমাপ করুন’ দেখুন।
অন্যান্য সকল প্রস্তাবিত বা কাস্টম ইভেন্টের জন্য
clientIdআবশ্যক। গুগল অ্যানালিটিক্স মেজারমেন্ট প্রোটোকল (Google Analytics Measurement Protocol) নির্দেশাবলী দেখুন।App data stream
-
appInstanceId: আবশ্যক । অ্যাপ ক্লায়েন্টের ব্যবহারকারী ইনস্ট্যান্সের জন্য এটিকে একটি অনন্য শনাক্তকারী হিসাবে সেট করুন। গুগল অ্যানালিটিক্স মেজারমেন্ট প্রোটোকল নির্দেশাবলী দেখুন।
-
destinationReferences Required if the request-level
destinationslist contains more than one Google AnalyticsDestination. Add an entry todestinationReferencesto specify which Google Analytics destination should receive the event. See send events to multiple destinations for more information about destination references.If
destinationReferencesisn't set or has multiple entries that refer to Google Analytics destinations, the Data Manager API rejects the event with the errorMULTIPLE_DESTINATIONS_FOR_GOOGLE_ANALYTICS_EVENT.-
cartData ইভেন্টটির জন্য গুগল অ্যানালিটিক্স ইভেন্ট স্পেসিফিকেশনে নির্দেশিত থাকলে এটি আবশ্যক ।
Learn how to add cart data to your events.
-
userId Optional. The User-ID for the user.
-
userProperties ঐচ্ছিক। ব্যবহারকারীর বৈশিষ্ট্যসমূহ । প্রতিটি ব্যবহারকারীর বৈশিষ্ট্যের জন্য
additionalUserPropertiesতালিকায় একটি পৃথক এন্ট্রি যোগ করুন।-
additionalEventParameters Optional, but recommended. Populate this list with any Google Analytics event parameters that aren't captured in the other
Eventfields. The parameters can include additional recommended parameters for the event or any other parameters you want to capture. Use the Google Analytics parameter name for theparameterNameof theEventParameter.উদাহরণস্বরূপ, যদি আপনার কাছে কোনো লেনদেনের সাথে যুক্ত কর থাকে, তাহলে
additionalEventParametersএ একটি এন্ট্রি যোগ করুন, যেখানেparameterNametaxএবংvalueকরের পরিমাণ হিসেবে সেট করা হবে।আমরা
transactionId,currency, বাvalueগুগল অ্যানালিটিক্স ইভেন্ট প্যারামিটারগুলোর জন্যadditionalEventParametersএ এন্ট্রি যোগ করার পরামর্শ দিই না। এর পরিবর্তে,Eventএর `transactionId,currency, এবংconversionValueফিল্ডগুলো পূরণ করুন, যেগুলোadditionalEventParametersএর যেকোনো এন্ট্রির চেয়ে অগ্রাধিকার পায়।
Add cart data
Populate the cartData field of the Event with information about the items associated with the event. Use this field when sending Google Analytics recommended events such as purchase that require an items list, Google Ads conversions with cart data parameters , Google Ads store sales conversions, or Floodlight conversions.
প্রয়োজন অনুযায়ী CartData জন্য নিম্নলিখিত ক্ষেত্রগুলি পূরণ করুন।
-
items - আবশ্যক । এই তালিকা থেকে অন্তত একটি বিষয় অন্তর্ভুক্ত করুন।
Merchant Center fields
The merchantId , merchantFeedLabel , and merchantFeedLanguageCode are all optional. Set these fields for Google Ads conversions with cart data if the items in the event include products that exist in several Merchant Center accounts.
-
merchantId - Optional. The Merchant Center account ID.
-
merchantFeedLabel - Optional. The feed label of the Merchant Center feed. Feed labels allow you to categorize products for campaign targeting. For example, you can use feed labels to organize products by language. If your campaign targets products based on country, use the 2-letter country code in ISO-3166-1 alpha-2 format. Example:
US. -
merchantFeedLanguageCode - ঐচ্ছিক। মার্চেন্ট সেন্টার ফিডের সাথে যুক্ত ISO 639-1 ভাষা কোড, যেখানে আপনার আইটেমগুলো আপলোড করা হয়। উদাহরণ:
en।
Add item-level cart data
CartData এর items তালিকায় এক বা একাধিক Item অবজেক্ট যোগ করুন। কার্ট ডেটা সহ Google Ads কনভার্সন এবং Google Analytics-এর প্রস্তাবিত ইভেন্ট , যেমন purchase ), যেগুলোর জন্য items তালিকা প্রয়োজন, সেগুলোর ক্ষেত্রে items তালিকাটি খালি থাকা যাবে না।
প্রয়োজন অনুযায়ী প্রতিটি Item জন্য নিম্নলিখিত ক্ষেত্রগুলি পূরণ করুন।
গুগল অ্যানালিটিক্স
এখানে গুগল অ্যানালিটিক্স-এর প্রস্তাবিত ইভেন্ট , যেমন purchase , যার জন্য একটি items তালিকা প্রয়োজন, তার শর্তাবলী দেওয়া হলো।
-
items.itemId - Required . A unique identifier for the item.
-
items.unitPrice Optional. The unit price excluding tax, shipping, and event scoped (transaction-level) discounts for this item.
যদি আইটেমটিতে আইটেম-ভিত্তিক ছাড় থাকে, তাহলে ছাড়-পরবর্তী একক মূল্য ব্যবহার করুন। উদাহরণস্বরূপ, যদি কোনো আইটেমের একক মূল্য
27.67এবং একক ছাড়6.66হয়, তাহলেunitPrice21.01নির্ধারণ করুন।-
items.quantity Required . The quantity of units for this particular item.
-
items.additionalItemParameters ঐচ্ছিক। এই তালিকাটি এমন যেকোনো আইটেম-ভিত্তিক প্যারামিটার দিয়ে পূরণ করুন যা অন্য
Itemফিল্ডগুলিতে অন্তর্ভুক্ত নয়।ItemParameterএরparameterNameহিসেবে Google Analytics ডকুমেন্টেশন থেকে প্যারামিটারের নামটি ব্যবহার করুন।উদাহরণস্বরূপ, গুগল অ্যানালিটিক্স-এর ক্ষেত্রে, যদি আপনার কাছে কোনো
purchaseইভেন্টের আইটেমের ব্র্যান্ড এবং ক্যাটাগরি জানা থাকে, তাহলে আইটেমটিরadditionalItemParametersএ একটি এন্ট্রি যোগ করুন, যেখানেparameterNameitem_brandএবংvalueব্র্যান্ডের নামে সেট করা থাকবে।আমরা
quantity,price, বাitem_idআইটেম প্যারামিটারগুলোর জন্যadditionalItemParametersএ এন্ট্রি যোগ করার পরামর্শ দিই না। এর পরিবর্তে,ItemএরitemId,unitPrice, এবংquantityফিল্ডগুলো পূরণ করুন, যেগুলোadditionalItemParametersএর যেকোনো এন্ট্রির চেয়ে অগ্রাধিকার পায়।
Google Ads store sales
গুগল অ্যাডস স্টোরের সেলস কনভার্সনের জন্য প্রয়োজনীয় শর্তাবলী নিচে দেওয়া হলো।
-
items.itemId - Optional. A unique identifier for the item.
-
items.merchantProductId - ঐচ্ছিক। মার্চেন্ট সেন্টার অ্যাকাউন্টের অন্তর্ভুক্ত প্রোডাক্ট আইডি ।
-
items.quantity - ঐচ্ছিক। এই নির্দিষ্ট আইটেমটির জন্য ক্রয়কৃত ইউনিটের পরিমাণ। সেট না করা হলে ডিফল্ট মান
1হবে। -
items.unitPrice ঐচ্ছিক। এই আইটেমটির জন্য ট্যাক্স, শিপিং এবং ইভেন্ট-ভিত্তিক (লেনদেন-স্তরের) ডিসকাউন্ট বাদে একক মূল্যে সেট করুন।
যদি আইটেমটিতে আইটেম-ভিত্তিক ছাড় থাকে, তাহলে ছাড়-পরবর্তী একক মূল্য ব্যবহার করুন। উদাহরণস্বরূপ, যদি কোনো আইটেমের একক মূল্য
27.67এবং একক ছাড়6.66হয়, তাহলেunitPrice21.01নির্ধারণ করুন।-
items.conversionValue ঐচ্ছিক। এই আইটেমটির একটি ইউনিটের জন্য রূপান্তর মান। উদাহরণস্বরূপ, যদি কোনো আইটেমের দুটি ইউনিট প্রতিটি $10.00 মূল্যে কেনা হয়, তাহলে
items.conversionValueকে10.00এবংitems.quantityকে2সেট করুন। মনে রাখবেন যে, যদিও এই ফিল্ডটি স্বতন্ত্র আইটেমের জন্য ঐচ্ছিক, স্টোরের বিক্রয় রূপান্তর আপলোড করার সময় ইভেন্ট-স্তরেরconversionValueফিল্ডটি আবশ্যক।-
items.customVariables ঐচ্ছিক। গুগল অ্যাডস কনভার্সন অ্যাকশনে পাঠানোর জন্য অতিরিক্ত কী-ভ্যালু পেয়ার ডেটা, যা
CustomVariableঅবজেক্টের একটি তালিকা হিসাবে নির্দিষ্ট করা হয়।
Google Ads with cart data
যেসব গুগল অ্যাডস ইভেন্ট স্টোর সেলস কনভার্সন নয়, সেগুলোর সাথে কার্ট ডেটা পাঠানোর জন্য প্রয়োজনীয় শর্তাবলী এখানে দেওয়া হলো। যদি আপনার ইভেন্টগুলো গুগল অ্যাডস স্টোর সেলস কনভার্সন হয়, তাহলে এর পরিবর্তে গুগল অ্যাডস স্টোর সেলস-এর শর্তাবলী দেখুন।
-
items.itemId - Required . A unique identifier for the item.
-
items.merchantProductId - মার্চেন্ট সেন্টার অ্যাকাউন্টের অন্তর্গত প্রোডাক্ট আইডিটি আবশ্যক ।
-
items.unitPrice আবশ্যক । এই আইটেমটির একক মূল্য, কর, শিপিং এবং ইভেন্ট-ভিত্তিক (লেনদেন-স্তরের) ছাড় ব্যতীত।
যদি আইটেমটিতে আইটেম-ভিত্তিক ছাড় থাকে, তাহলে ছাড়-পরবর্তী একক মূল্য ব্যবহার করুন। উদাহরণস্বরূপ, যদি কোনো আইটেমের একক মূল্য
27.67এবং একক ছাড়6.66হয়, তাহলেunitPrice21.01নির্ধারণ করুন।-
items.quantity প্রয়োজনীয় । এই নির্দিষ্ট পণ্যটির জন্য ক্রয়কৃত ইউনিটের পরিমাণ।
ফ্লাডলাইট
ফ্ল্যাডলাইটে ইভেন্ট পাঠানোর জন্য প্রয়োজনীয় শর্তাবলী নিচে দেওয়া হলো।
-
items.itemId - Optional. A unique identifier for the item.
-
items.merchantProductId - Required . The product ID within the Merchant Center account.
-
items.unitPrice আবশ্যক । এই আইটেমটির একক মূল্য, কর, শিপিং এবং ইভেন্ট-ভিত্তিক (লেনদেন-স্তরের) ছাড় ব্যতীত।
যদি আইটেমটিতে আইটেম-ভিত্তিক ছাড় থাকে, তাহলে ছাড়-পরবর্তী একক মূল্য ব্যবহার করুন। উদাহরণস্বরূপ, যদি কোনো আইটেমের একক মূল্য
27.67এবং একক ছাড়6.66হয়, তাহলেunitPrice21.01নির্ধারণ করুন।-
items.quantity প্রয়োজনীয় । এই নির্দিষ্ট পণ্যটির জন্য ক্রয়কৃত ইউনিটের পরিমাণ।
Sample requests
গুগল অ্যানালিটিক্স
এখানে দ্বিতীয় ইভেন্ট থেকে ফরম্যাট করা, হ্যাশ করা এবং এনকোড করা ডেটার একটি নমুনা Event হলো, সাথে গুগল অ্যানালিটিক্সের জন্য অতিরিক্ত ডেটাও রয়েছে:
{
"adIdentifiers": {
"gclid": "GCLID_2"
},
"conversionValue": 42.02,
"currency": "EUR",
"eventTimestamp": "2025-06-10T23:42:33-05:00",
"transactionId": "DEF999911111",
"eventSource": "WEB",
"userData": {
"userIdentifiers": [
{
"emailAddress": "3E693CF7E5B67880BFF33B2D2626DADB7BF1D4BC737192E47CF8BAA89ACF2250"
},
{
"emailAddress": "223EBDA6F6889B1494551BA902D9D381DAF2F642BAE055888E96343D53E9F9C4"
},
{
"address": {
"givenName": "2752B88686847FA5C86F47B94CE652B7B3F22A91C37617D451A4DB9AFA431450",
"familyName": "6654977D57DDDD3C0329CA741B109EF6CD6430BEDD00008AAD213DF25683D77F",
"regionCode": "PT",
"postalCode": "1229-076"
}
}
],
},
"userProperties": {
"customerType": "RETURNING"
},
"eventName": "purchase",
"clientId": "9876543210.1761582117",
"userId": "user_DEF9876",
"additionalEventParameters": [
{
"parameterName": "ad_unit_name",
"value": "Banner_02"
}
],
"cartData": {
"transactionDiscount": 6.66,
"items": [
{
"itemId": "SKU_12346",
"quantity": 2,
"unitPrice": 21.01,
"additionalItemParameters": [
{
"parameterName": "item_name",
"value": "Google Grey Women's Tee"
},
{
"parameterName": "affiliation",
"value": "Google Merchandise Store"
},
{
"parameterName": "coupon",
"value": "SUMMER_FUN"
},
{
"parameterName": "discount",
"value": "3.33"
},
{
"parameterName": "index",
"value": "1"
},
{
"parameterName": "item_brand",
"value": "Google"
},
{
"parameterName": "item_category",
"value": "Apparel"
},
{
"parameterName": "item_category2",
"value": "Adult"
},
{
"parameterName": "item_category3",
"value": "Shirts"
},
{
"parameterName": "item_category4",
"value": "Crew"
},
{
"parameterName": "item_category5",
"value": "Short sleeve"
},
{
"parameterName": "item_list_id",
"value": "related_products"
},
{
"parameterName": "item_list_name",
"value": "Related Products"
}
]
}
]
}
}
Google Ads store sales
গুগল অ্যাডস স্টোরের বিক্রয় রূপান্তরের একটি উদাহরণ হিসেবে, এখানে তৃতীয় ইভেন্ট থেকে ফরম্যাট করা, হ্যাশ করা এবং এনকোড করা ডেটার একটি নমুনা Event দেওয়া হলো:
{
"conversionValue": 450.0,
"currency": "USD",
"eventTimestamp": "2025-06-11T12:05:00-04:00",
"transactionId": "XYZ987654321",
"eventSource": "IN_STORE",
"eventLocation": {
"storeId": "STORE_NY_001"
},
"userData": {
"userIdentifiers": [
{
"address": {
"givenName": "B9DD960C1753459A78115D3CB845A57D924B6877E805B08BD01086CCDF34433C",
"familyName": "DB98D2607EFFFA28AFF66975868BF54C075ECA7157E35064DCE08E20B85B1081",
"regionCode": "US",
"postalCode": "10011"
}
}
]
},
"cartData": {
"merchantId": "123",
"merchantFeedLabel": "US",
"merchantFeedLanguageCode": "en",
"items": [
{
"merchantProductId": "ITEM_SKU_987",
"quantity": 1,
"conversionValue": 450.0,
"customVariables": [
{
"variable": "DEPARTMENT",
"value": "ELECTRONICS"
}
]
}
]
}
}
Build the request body
রিকোয়েস্ট বডি তৈরি করতে, destinations এবং events একত্রিত করুন, encoding ফিল্ড সেট করুন, এবং আপনার ইচ্ছামত অন্য যেকোনো রিকোয়েস্ট ফিল্ড, যেমন validateOnly ও consent , যোগ করুন।
এই নির্দেশিকার উদাহরণগুলিতে এনক্রিপশন ব্যবহার করা হয়নি, কিন্তু আপনি আপনার প্রক্রিয়ায় এনক্রিপশন যোগ করতে ‘ব্যবহারকারীর ডেটা এনক্রিপ্ট করুন ’ অংশের নির্দেশাবলী অনুসরণ করতে পারেন।
অনুরোধ পাঠান
আপনার ব্রাউজার থেকে অনুরোধ চেষ্টা করার ধাপগুলো নিচে দেওয়া হলো:
- REST ট্যাবটি নির্বাচন করুন এবং একটি নতুন ট্যাব বা উইন্ডোতে API Explorer খোলার জন্য Open in API Explorer-এ ক্লিক করুন।
- এপিআই এক্সপ্লোরারে রিকোয়েস্ট বডিতে,
REPLACE_WITHদিয়ে শুরু হওয়া প্রতিটি স্ট্রিং, যেমনREPLACE_WITH_OPERATING_ACCOUNT_TYPE, প্রাসঙ্গিক মান দিয়ে প্রতিস্থাপন করুন। - অনুরোধটি পাঠানোর জন্য API Explorer পেজের নিচে থাকা Execute বাটনে ক্লিক করুন এবং অনুমোদনের নির্দেশাবলী পূরণ করুন।
- পরিবর্তনগুলো প্রয়োগ না করে অনুরোধটি যাচাই করতে
validateOnlyকেtrueসেট করুন। যখন আপনি পরিবর্তনগুলো প্রয়োগ করতে প্রস্তুত হবেন, তখনvalidateOnlyকেfalseসেট করুন।
আপনি যদি কোনো ক্লায়েন্ট লাইব্রেরি ইনস্টল করে থাকেন , তাহলে কীভাবে একটি অনুরোধ তৈরি ও প্রেরণ করতে হয় তার সম্পূর্ণ কোড নমুনা দেখতে আপনার নির্বাচিত প্রোগ্রামিং ভাষার ট্যাবটি নির্বাচন করুন।
বিশ্রাম
বিজ্ঞাপনদাতা
{ "destinations": [ { "operatingAccount": { "accountType": "OPERATING_ACCOUNT_TYPE", "accountId": "OPERATING_ACCOUNT_ID" }, "loginAccount": { "accountType": "LOGIN_ACCOUNT_TYPE", "accountId": "LOGIN_ACCOUNT_ID" }, "productDestinationId": "CONVERSION_ACTION_ID" } ], "encoding": "HEX", "events": [ { "adIdentifiers": { "gclid": "GCLID_1" }, "conversionValue": 30.03, "currency": "USD", "eventTimestamp": "2025-06-10T20:07:01Z", "transactionId": "ABC798654321", "eventSource": "WEB", "userData": { "userIdentifiers": [ { "address": { "givenName": "96D9632F363564CC3032521409CF22A852F2032EEC099ED5967C0D000CEC607A", "familyName": "DB98D2607EFFFA28AFF66975868BF54C075ECA7157E35064DCE08E20B85B1081", "regionCode": "US", "postalCode": "94045" } } ] }, "userProperties": { "customerType": "NEW", "customerValueBucket": "HIGH" }, "eventName": "purchase", "clientId": "1234567890.1761581763", "userId": "user_ABC12345", "additionalEventParameters": [ { "parameterName": "ad_unit_name", "value": "Banner_01" } ], "cartData": { "transactionDiscount": 6.66, "items": [ { "itemId": "SKU_12345", "quantity": 3, "unitPrice": 10.01, "additionalItemParameters": [ { "parameterName": "item_name", "value": "Stan and Friends Tee" }, { "parameterName": "affiliation", "value": "Google Merchandise Store" }, { "parameterName": "coupon", "value": "SUMMER_FUN" }, { "parameterName": "discount", "value": "2.22" }, { "parameterName": "index", "value": "0" }, { "parameterName": "item_brand", "value": "Google" }, { "parameterName": "item_category", "value": "Apparel" }, { "parameterName": "item_category2", "value": "Adult" }, { "parameterName": "item_category3", "value": "Shirts" }, { "parameterName": "item_category4", "value": "Crew" }, { "parameterName": "item_category5", "value": "Short sleeve" }, { "parameterName": "item_list_id", "value": "related_products" }, { "parameterName": "item_list_name", "value": "Related Products" } ] } ] } }, { "adIdentifiers": { "gclid": "GCLID_2" }, "conversionValue": 42.02, "currency": "EUR", "eventTimestamp": "2025-06-11T04:42:33Z", "transactionId": "DEF999911111", "eventSource": "WEB", "userData": { "userIdentifiers": [ { "emailAddress": "3E693CF7E5B67880BFF33B2D2626DADB7BF1D4BC737192E47CF8BAA89ACF2250" }, { "emailAddress": "223EBDA6F6889B1494551BA902D9D381DAF2F642BAE055888E96343D53E9F9C4" }, { "address": { "givenName": "2752B88686847FA5C86F47B94CE652B7B3F22A91C37617D451A4DB9AFA431450", "familyName": "6654977D57DDDD3C0329CA741B109EF6CD6430BEDD00008AAD213DF25683D77F", "regionCode": "PT", "postalCode": "1229-076" } } ] }, "userProperties": { "customerType": "RETURNING" }, "eventName": "purchase", "clientId": "9876543210.1761582117", "userId": "user_DEF9876", "additionalEventParameters": [ { "parameterName": "ad_unit_name", "value": "Banner_02" } ], "cartData": { "transactionDiscount": 6.66, "items": [ { "itemId": "SKU_12346", "quantity": 2, "unitPrice": 21.01, "additionalItemParameters": [ { "parameterName": "item_name", "value": "Google Grey Women's Tee" }, { "parameterName": "affiliation", "value": "Google Merchandise Store" }, { "parameterName": "coupon", "value": "SUMMER_FUN" }, { "parameterName": "discount", "value": "3.33" }, { "parameterName": "index", "value": "1" }, { "parameterName": "item_brand", "value": "Google" }, { "parameterName": "item_category", "value": "Apparel" }, { "parameterName": "item_category2", "value": "Adult" }, { "parameterName": "item_category3", "value": "Shirts" }, { "parameterName": "item_category4", "value": "Crew" }, { "parameterName": "item_category5", "value": "Short sleeve" }, { "parameterName": "item_list_id", "value": "related_products" }, { "parameterName": "item_list_name", "value": "Related Products" } ] } ] } } ], "validateOnly": true }
Data Partner
{ "destinations": [ { "operatingAccount": { "accountType": "OPERATING_ACCOUNT_TYPE", "accountId": "OPERATING_ACCOUNT_ID" }, "loginAccount": { "accountType": "DATA_PARTNER", "accountId": "DATA_PARTNER_ACCOUNT_ID" }, "linkedAccount": { "accountType": "LINKED_ACCOUNT_TYPE", "accountId": "LINKED_ACCOUNT_ID" }, "productDestinationId": "CONVERSION_ACTION_ID" } ], "encoding": "HEX", "events": [ { "adIdentifiers": { "gclid": "GCLID_1" }, "conversionValue": 30.03, "currency": "USD", "eventTimestamp": "2025-06-10T20:07:01Z", "transactionId": "ABC798654321", "eventSource": "WEB", "userData": { "userIdentifiers": [ { "address": { "givenName": "96D9632F363564CC3032521409CF22A852F2032EEC099ED5967C0D000CEC607A", "familyName": "DB98D2607EFFFA28AFF66975868BF54C075ECA7157E35064DCE08E20B85B1081", "regionCode": "US", "postalCode": "94045" } } ] }, "userProperties": { "customerType": "NEW", "customerValueBucket": "HIGH" }, "eventName": "purchase", "clientId": "1234567890.1761581763", "userId": "user_ABC12345", "additionalEventParameters": [ { "parameterName": "ad_unit_name", "value": "Banner_01" } ], "cartData": { "transactionDiscount": 6.66, "items": [ { "itemId": "SKU_12345", "quantity": 3, "unitPrice": 10.01, "additionalItemParameters": [ { "parameterName": "item_name", "value": "Stan and Friends Tee" }, { "parameterName": "affiliation", "value": "Google Merchandise Store" }, { "parameterName": "coupon", "value": "SUMMER_FUN" }, { "parameterName": "discount", "value": "2.22" }, { "parameterName": "index", "value": "0" }, { "parameterName": "item_brand", "value": "Google" }, { "parameterName": "item_category", "value": "Apparel" }, { "parameterName": "item_category2", "value": "Adult" }, { "parameterName": "item_category3", "value": "Shirts" }, { "parameterName": "item_category4", "value": "Crew" }, { "parameterName": "item_category5", "value": "Short sleeve" }, { "parameterName": "item_list_id", "value": "related_products" }, { "parameterName": "item_list_name", "value": "Related Products" } ] } ] } }, { "adIdentifiers": { "gclid": "GCLID_2" }, "conversionValue": 42.02, "currency": "EUR", "eventTimestamp": "2025-06-11T04:42:33Z", "transactionId": "DEF999911111", "eventSource": "WEB", "userData": { "userIdentifiers": [ { "emailAddress": "3E693CF7E5B67880BFF33B2D2626DADB7BF1D4BC737192E47CF8BAA89ACF2250" }, { "emailAddress": "223EBDA6F6889B1494551BA902D9D381DAF2F642BAE055888E96343D53E9F9C4" }, { "address": { "givenName": "2752B88686847FA5C86F47B94CE652B7B3F22A91C37617D451A4DB9AFA431450", "familyName": "6654977D57DDDD3C0329CA741B109EF6CD6430BEDD00008AAD213DF25683D77F", "regionCode": "PT", "postalCode": "1229-076" } } ] }, "userProperties": { "customerType": "RETURNING" }, "eventName": "purchase", "clientId": "9876543210.1761582117", "userId": "user_DEF9876", "additionalEventParameters": [ { "parameterName": "ad_unit_name", "value": "Banner_02" } ], "cartData": { "transactionDiscount": 6.66, "items": [ { "itemId": "SKU_12346", "quantity": 2, "unitPrice": 21.01, "additionalItemParameters": [ { "parameterName": "item_name", "value": "Google Grey Women's Tee" }, { "parameterName": "affiliation", "value": "Google Merchandise Store" }, { "parameterName": "coupon", "value": "SUMMER_FUN" }, { "parameterName": "discount", "value": "3.33" }, { "parameterName": "index", "value": "1" }, { "parameterName": "item_brand", "value": "Google" }, { "parameterName": "item_category", "value": "Apparel" }, { "parameterName": "item_category2", "value": "Adult" }, { "parameterName": "item_category3", "value": "Shirts" }, { "parameterName": "item_category4", "value": "Crew" }, { "parameterName": "item_category5", "value": "Short sleeve" }, { "parameterName": "item_list_id", "value": "related_products" }, { "parameterName": "item_list_name", "value": "Related Products" } ] } ] } } ], "validateOnly": true }
.NET
// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Text.Json; using CommandLine; using Google.Ads.DataManager.Util; using Google.Ads.DataManager.V1; using Google.Protobuf.WellKnownTypes; using static Google.Ads.DataManager.V1.ProductAccount.Types; namespace Google.Ads.DataManager.Samples { // <summary> // Sends an <see cref="IngestEventsRequest" /> without using encryption. // // Event data is read from a data file. See the <c>events_1.json</c> file in the // <c>sampledata</c> directory for an example. // </summary> public class IngestEvents { private static readonly int MaxEventsPerRequest = 2_000; [Verb("ingest-events", HelpText = "Sends an IngestEventsRequest without using encryption.")] public class Options { [Option( "operatingAccountType", Required = true, HelpText = "Account type of the operating account" )] public AccountType OperatingAccountType { get; set; } [Option( "operatingAccountId", Required = true, HelpText = "ID of the operating account" )] public string OperatingAccountId { get; set; } = null!; [Option( "loginAccountType", Required = false, HelpText = "Account type of the login account" )] public AccountType? LoginAccountType { get; set; } [Option("loginAccountId", Required = false, HelpText = "ID of the login account")] public string? LoginAccountId { get; set; } [Option( "linkedAccountProduct", Required = false, HelpText = "Account type of the linked account" )] public AccountType? LinkedAccountType { get; set; } [Option("linkedAccountId", Required = false, HelpText = "ID of the linked account")] public string? LinkedAccountId { get; set; } [Option( "conversionActionId", Required = true, HelpText = "ID of the conversion action" )] public string ConversionActionId { get; set; } = null!; [Option( "jsonFile", Required = true, HelpText = "JSON file containing user data to ingest" )] public string JsonFile { get; set; } = null!; [Option( "validateOnly", Default = true, HelpText = "Whether to enable validateOnly on the request" )] public bool ValidateOnly { get; set; } } public void Run(Options options) { RunExample( options.OperatingAccountType, options.OperatingAccountId, options.LoginAccountType, options.LoginAccountId, options.LinkedAccountType, options.LinkedAccountId, options.ConversionActionId, options.JsonFile, options.ValidateOnly ); } private void RunExample( AccountType operatingAccountType, string operatingAccountId, AccountType? loginAccountType, string? loginAccountId, AccountType? linkedAccountType, string? linkedAccountId, string conversionActionId, string jsonFile, bool validateOnly ) { if (loginAccountId == null ^ loginAccountType == null) { throw new ArgumentException( "Must specify either both or neither of login account ID and login account " + "type" ); } if (linkedAccountId == null ^ linkedAccountType == null) { throw new ArgumentException( "Must specify either both or neither of linked account ID and linked account " + "type" ); } // Reads member data from the data file. List<EventRecord> eventRecords = ReadEventData(jsonFile); // Gets an instance of the UserDataFormatter for normalizing and formatting the data. UserDataFormatter userDataFormatter = new UserDataFormatter(); // Builds the events collection for the request. var events = new List<Event>(); foreach (var eventRecord in eventRecords) { var eventBuilder = new Event(); try { eventBuilder.EventTimestamp = Timestamp.FromDateTime( DateTime.Parse(eventRecord.Timestamp ?? "").ToUniversalTime() ); } catch (FormatException) { Console.WriteLine( $"Skipping event with invalid timestamp: {eventRecord.Timestamp}" ); continue; } if (string.IsNullOrEmpty(eventRecord.TransactionId)) { Console.WriteLine("Skipping event with no transaction ID"); continue; } eventBuilder.TransactionId = eventRecord.TransactionId; if (!string.IsNullOrEmpty(eventRecord.EventSource)) { if ( System.Enum.TryParse( eventRecord.EventSource, true, out EventSource eventSource ) ) { eventBuilder.EventSource = eventSource; } else { Console.WriteLine( $"Skipping event with invalid event source: {eventRecord.EventSource}" ); continue; } } if (!string.IsNullOrEmpty(eventRecord.Gclid)) { eventBuilder.AdIdentifiers = new AdIdentifiers { Gclid = eventRecord.Gclid }; } if (!string.IsNullOrEmpty(eventRecord.Currency)) { eventBuilder.Currency = eventRecord.Currency; } if (eventRecord.Value.HasValue) { eventBuilder.ConversionValue = eventRecord.Value.Value; } var userDataBuilder = new UserData(); // Adds a UserIdentifier for each valid email address for the eventRecord. if (eventRecord.Emails != null) { foreach (var email in eventRecord.Emails) { try { string preparedEmail = userDataFormatter.ProcessEmailAddress( email, UserDataFormatter.Encoding.Hex ); // Adds an email address identifier with the encoded email hash. userDataBuilder.UserIdentifiers.Add( new UserIdentifier { EmailAddress = preparedEmail } ); } catch (ArgumentException) { // Skips invalid input. continue; } } } // Adds a UserIdentifier for each valid phone number for the eventRecord. if (eventRecord.PhoneNumbers != null) { foreach (var phoneNumber in eventRecord.PhoneNumbers) { try { string preparedPhoneNumber = userDataFormatter.ProcessPhoneNumber( phoneNumber, UserDataFormatter.Encoding.Hex ); // Adds a phone number identifier with the encoded phone hash. userDataBuilder.UserIdentifiers.Add( new UserIdentifier { PhoneNumber = preparedPhoneNumber } ); } catch (ArgumentException) { // Skips invalid input. continue; } } } if (userDataBuilder.UserIdentifiers.Any()) { eventBuilder.UserData = userDataBuilder; } events.Add(eventBuilder); } // Builds the Destination for the request. var destinationBuilder = new Destination { OperatingAccount = new ProductAccount { AccountType = operatingAccountType, AccountId = operatingAccountId, }, ProductDestinationId = conversionActionId, }; if (loginAccountType.HasValue && loginAccountId != null) { destinationBuilder.LoginAccount = new ProductAccount { AccountType = loginAccountType.Value, AccountId = loginAccountId, }; } if (linkedAccountType.HasValue && linkedAccountId != null) { destinationBuilder.LinkedAccount = new ProductAccount { AccountType = linkedAccountType.Value, AccountId = linkedAccountId, }; } IngestionServiceClient ingestionServiceClient = IngestionServiceClient.Create(); int requestCount = 0; // Batches requests to send up to the maximum number of events per request. for (var i = 0; i < events.Count; i += MaxEventsPerRequest) { IEnumerable<Event> batch = events.Skip(i).Take(MaxEventsPerRequest); requestCount++; var request = new IngestEventsRequest { Destinations = { destinationBuilder }, // Adds events from the current batch. Events = { batch }, Consent = new Consent { AdPersonalization = ConsentStatus.ConsentGranted, AdUserData = ConsentStatus.ConsentGranted, }, // Sets validate_only. If true, then the Data Manager API only validates the // request but doesn't apply changes. ValidateOnly = validateOnly, Encoding = V1.Encoding.Hex, }; // Sends the data to the Data Manager API. IngestEventsResponse response = ingestionServiceClient.IngestEvents(request); Console.WriteLine($"Response for request #{requestCount}:\n{response}"); } Console.WriteLine($"# of requests sent: {requestCount}"); } private class EventRecord { public List<string>? Emails { get; set; } public List<string>? PhoneNumbers { get; set; } public string? Timestamp { get; set; } public string? TransactionId { get; set; } public string? EventSource { get; set; } public double? Value { get; set; } public string? Currency { get; set; } public string? Gclid { get; set; } } private List<EventRecord> ReadEventData(string jsonFile) { string jsonString = File.ReadAllText(jsonFile); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; return JsonSerializer.Deserialize<List<EventRecord>>(jsonString, options) ?? new List<EventRecord>(); } } }
জাভা
// Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package com.google.ads.datamanager.samples; import com.beust.jcommander.Parameter; import com.google.ads.datamanager.samples.common.BaseParamsConfig; import com.google.ads.datamanager.util.UserDataFormatter; import com.google.ads.datamanager.util.UserDataFormatter.Encoding; import com.google.ads.datamanager.v1.AdIdentifiers; import com.google.ads.datamanager.v1.Consent; import com.google.ads.datamanager.v1.ConsentStatus; import com.google.ads.datamanager.v1.Destination; import com.google.ads.datamanager.v1.Event; import com.google.ads.datamanager.v1.EventSource; import com.google.ads.datamanager.v1.IngestEventsRequest; import com.google.ads.datamanager.v1.IngestEventsResponse; import com.google.ads.datamanager.v1.IngestionServiceClient; import com.google.ads.datamanager.v1.ProductAccount; import com.google.ads.datamanager.v1.ProductAccount.AccountType; import com.google.ads.datamanager.v1.UserData; import com.google.ads.datamanager.v1.UserIdentifier; import com.google.common.base.Strings; import com.google.common.collect.Lists; import com.google.common.reflect.TypeToken; import com.google.gson.GsonBuilder; import com.google.protobuf.util.Timestamps; import java.io.BufferedReader; import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.text.ParseException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; /** * Sends an {@link IngestEventsRequest} without using encryption. * * <p>Event data is read from a data file. See the {@code events_1.json} file in the {@code * resources/sampledata} directory for a sample file. */ public class IngestEvents { private static final Logger LOGGER = Logger.getLogger(IngestEvents.class.getName()); /** The maximum number of events allowed per request. */ private static final int MAX_EVENTS_PER_REQUEST = 2_000; private static final class ParamsConfig extends BaseParamsConfig<ParamsConfig> { @Parameter( names = "--operatingAccountType", required = true, description = "Account type of the operating account") AccountType operatingAccountType; @Parameter( names = "--operatingAccountId", required = true, description = "ID of the operating account") String operatingAccountId; @Parameter( names = "--loginAccountType", required = false, description = "Account type of the login account") AccountType loginAccountType; @Parameter( names = "--loginAccountId", required = false, description = "ID of the login account") String loginAccountId; @Parameter( names = "--linkedAccountType", required = false, description = "Account type of the linked account") AccountType linkedAccountType; @Parameter( names = "--linkedAccountId", required = false, description = "ID of the linked account") String linkedAccountId; @Parameter( names = "--conversionActionId", required = true, description = "ID of the conversion action") String conversionActionId; @Parameter( names = "--jsonFile", required = true, description = "JSON file containing user data to ingest") String jsonFile; @Parameter( names = "--validateOnly", required = false, arity = 1, description = "Whether to enable validateOnly on the request") boolean validateOnly = true; } public static void main(String[] args) throws IOException { ParamsConfig paramsConfig = new ParamsConfig().parseOrExit(args); if ((paramsConfig.loginAccountId == null) != (paramsConfig.loginAccountType == null)) { throw new IllegalArgumentException( "Must specify either both or neither of login account ID and login account type"); } if ((paramsConfig.linkedAccountId == null) != (paramsConfig.linkedAccountType == null)) { throw new IllegalArgumentException( "Must specify either both or neither of linked account ID and linked account type"); } new IngestEvents().runExample(paramsConfig); } /** * Runs the example. This sample assumes that the login and operating account are the same. * * @param params the parameters for the example */ private void runExample(ParamsConfig params) throws IOException { // Reads event data from the JSON file. List<EventRecord> eventRecords = readEventData(params.jsonFile); // Gets an instance of the UserDataFormatter for normalizing and formatting the data. UserDataFormatter userDataFormatter = UserDataFormatter.create(); // Builds the events collection for the request. List<Event> events = new ArrayList<>(); for (EventRecord eventRecord : eventRecords) { Event.Builder eventBuilder = Event.newBuilder(); try { eventBuilder.setEventTimestamp(Timestamps.parse(eventRecord.timestamp)); } catch (ParseException pe) { LOGGER.warning( () -> String.format("Skipping event with invalid timestamp: %s", eventRecord.timestamp)); continue; } if (Strings.isNullOrEmpty(eventRecord.transactionId)) { LOGGER.warning("Skipping event with no transaction ID"); continue; } eventBuilder.setTransactionId(eventRecord.transactionId); if (!Strings.isNullOrEmpty(eventRecord.eventSource)) { try { eventBuilder.setEventSource(EventSource.valueOf(eventRecord.eventSource)); } catch (IllegalArgumentException iae) { LOGGER.warning("Skipping event with invalid event source: " + eventRecord.eventSource); continue; } } if (!Strings.isNullOrEmpty(eventRecord.gclid)) { eventBuilder.setAdIdentifiers(AdIdentifiers.newBuilder().setGclid(eventRecord.gclid)); } if (!Strings.isNullOrEmpty(eventRecord.currency)) { eventBuilder.setCurrency(eventRecord.currency); } if (eventRecord.value != null) { eventBuilder.setConversionValue(eventRecord.value); } UserData.Builder userDataBuilder = UserData.newBuilder(); // Adds a UserIdentifier for each valid email address for the eventRecord. if (eventRecord.emails != null) { for (String email : eventRecord.emails) { String preparedEmail; try { preparedEmail = userDataFormatter.processEmailAddress(email, Encoding.HEX); } catch (IllegalArgumentException iae) { // Skips invalid input. continue; } // Sets the email address identifier to the encoded email hash. userDataBuilder.addUserIdentifiers( UserIdentifier.newBuilder().setEmailAddress(preparedEmail)); } } // Adds a UserIdentifier for each valid phone number for the eventRecord. if (eventRecord.phoneNumbers != null) { for (String phoneNumber : eventRecord.phoneNumbers) { String preparedPhoneNumber; try { preparedPhoneNumber = userDataFormatter.processPhoneNumber(phoneNumber, Encoding.HEX); } catch (IllegalArgumentException iae) { // Skips invalid input. continue; } // Sets the phone number identifier to the encoded phone number hash. userDataBuilder.addUserIdentifiers( UserIdentifier.newBuilder().setPhoneNumber(preparedPhoneNumber)); } } if (userDataBuilder.getUserIdentifiersCount() > 0) { eventBuilder.setUserData(userDataBuilder); } events.add(eventBuilder.build()); } // Builds the Destination for the request. Destination.Builder destinationBuilder = Destination.newBuilder() .setOperatingAccount( ProductAccount.newBuilder() .setAccountType(params.operatingAccountType) .setAccountId(params.operatingAccountId)) .setProductDestinationId(params.conversionActionId); if (params.loginAccountType != null && params.loginAccountId != null) { destinationBuilder.setLoginAccount( ProductAccount.newBuilder() .setAccountType(params.loginAccountType) .setAccountId(params.loginAccountId)); } if (params.linkedAccountType != null && params.linkedAccountId != null) { destinationBuilder.setLinkedAccount( ProductAccount.newBuilder() .setAccountType(params.linkedAccountType) .setAccountId(params.linkedAccountId)); } try (IngestionServiceClient ingestionServiceClient = IngestionServiceClient.create()) { int requestCount = 0; // Batches requests to send up to the maximum number of events per request. for (List<Event> eventsBatch : Lists.partition(events, MAX_EVENTS_PER_REQUEST)) { requestCount++; // Builds the request. IngestEventsRequest request = IngestEventsRequest.newBuilder() .addDestinations(destinationBuilder) // Adds events from the current batch. .addAllEvents(eventsBatch) .setConsent( Consent.newBuilder() .setAdPersonalization(ConsentStatus.CONSENT_GRANTED) .setAdUserData(ConsentStatus.CONSENT_GRANTED)) // Sets validate_only. If true, then the Data Manager API only validates the request // but doesn't apply changes. .setValidateOnly(params.validateOnly) // Sets encoding to match the encoding used. .setEncoding(com.google.ads.datamanager.v1.Encoding.HEX) .build(); LOGGER.info(() -> String.format("Request:%n%s", request)); IngestEventsResponse response = ingestionServiceClient.ingestEvents(request); LOGGER.info(String.format("Response for request #:%n%s", requestCount, response)); } LOGGER.info("# of requests sent: " + requestCount); } } /** Data object for a single row of input data. */ @SuppressWarnings("unused") private static class EventRecord { private List<String> emails; private List<String> phoneNumbers; private String timestamp; private String transactionId; private String eventSource; private Double value; private String currency; private String gclid; } /** Reads the data file and parses each line into a {@link EventRecord} object. */ private List<EventRecord> readEventData(String jsonFile) throws IOException { try (BufferedReader jsonReader = Files.newBufferedReader(Paths.get(jsonFile), StandardCharsets.UTF_8)) { // Define the type for Gson to deserialize into (List of EventRecord objects) Type recordListType = new TypeToken<ArrayList<EventRecord>>() {}.getType(); // Parse the JSON string from the file into a List of EventRecord objects return new GsonBuilder().create().fromJson(jsonReader, recordListType); } } }
নোড
#!/usr/bin/env node // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. 'use strict'; import {IngestionServiceClient} from '@google-ads/datamanager'; import {protos} from '@google-ads/datamanager'; const { Event: DataManagerEvent, Destination, Encoding: DataManagerEncoding, EventSource, Consent, ConsentStatus, IngestEventsRequest, ProductAccount, UserData, UserIdentifier, } = protos.google.ads.datamanager.v1; import {UserDataFormatter, Encoding} from '@google-ads/data-manager-util'; import * as fs from 'fs'; import * as yargs from 'yargs'; const MAX_EVENTS_PER_REQUEST = 10000; interface Arguments { operating_account_type: string; operating_account_id: string; conversion_action_id: string; json_file: string; validate_only: boolean; login_account_type?: string; login_account_id?: string; linked_account_type?: string; linked_account_id?: string; [x: string]: unknown; } interface EventRow { timestamp: string; transactionId: string; eventSource?: string; gclid?: string; currency?: string; value?: number; emails?: string[]; phoneNumbers?: string[]; } /** * The main function for the IngestEvents sample. */ async function main() { const argv: Arguments = yargs .option('operating_account_type', { describe: 'The account type of the operating account.', type: 'string', required: true, }) .option('operating_account_id', { describe: 'The ID of the operating account.', type: 'string', required: true, }) .option('conversion_action_id', { describe: 'The ID of the conversion action.', type: 'string', required: true, }) .option('json_file', { describe: 'JSON file containing user data to ingest.', type: 'string', required: true, }) .option('validate_only', { describe: 'Whether to enable validate_only on the request.', type: 'boolean', default: true, }) .option('login_account_type', { describe: 'The account type of the login account.', type: 'string', }) .option('login_account_id', { describe: 'The ID of the login account.', type: 'string', }) .option('linked_account_type', { describe: 'The account type of the linked account.', type: 'string', }) .option('linked_account_id', { describe: 'The ID of the linked account.', type: 'string', }) .option('config', { describe: 'Path to a JSON file with arguments.', type: 'string', }) .config('config') .check((args: Arguments) => { if ( (args.login_account_type && !args.login_account_id) || (!args.login_account_type && args.login_account_id) ) { throw new Error( 'Must specify either both or neither of login account type ' + 'and login account ID', ); } if ( (args.linked_account_type && !args.linked_account_id) || (!args.linked_account_type && args.linked_account_id) ) { throw new Error( 'Must specify either both or neither of linked account type ' + 'and linked account ID', ); } return true; }) .parseSync(); // Reads event data from the JSON file. const eventRows: EventRow[] = readEventDataFile(argv.json_file); // Builds the events collection for the request. const events = []; const formatter = new UserDataFormatter(); for (const eventRow of eventRows) { const event = DataManagerEvent.create(); try { const date = new Date(eventRow.timestamp); event.eventTimestamp = { seconds: Math.floor(date.getTime() / 1000), nanos: (date.getTime() % 1000) * 1e6, }; } catch (e) { console.warn( `Invalid timestamp format: ${eventRow.timestamp}. Skipping row.`, ); continue; } if (!eventRow.transactionId) { console.warn('Skipping event with no transaction ID'); continue; } event.transactionId = eventRow.transactionId; if (eventRow.eventSource) { const eventSourceEnumValue: number | undefined = EventSource[eventRow.eventSource as keyof typeof EventSource]; if (eventSourceEnumValue === undefined) { console.warn( `Skipping event with invalid event_source: ${eventRow.eventSource}`, ); continue; } event.eventSource = eventSourceEnumValue; } if (eventRow.gclid) { event.adIdentifiers = {gclid: eventRow.gclid}; } if (eventRow.currency) { event.currency = eventRow.currency; } if (eventRow.value) { event.conversionValue = eventRow.value; } const userData = UserData.create(); // Adds a UserIdentifier for each valid email address for the eventRecord. if (eventRow.emails) { for (const email of eventRow.emails) { try { const processedEmail = formatter.processEmailAddress( email, Encoding.HEX, ); userData.userIdentifiers.push( UserIdentifier.create({emailAddress: processedEmail}), ); } catch (e) { console.warn(`Invalid email address: ${email}. Skipping.`); } } } // Adds a UserIdentifier for each valid phone number for the eventRecord. if (eventRow.phoneNumbers) { for (const phoneNumber of eventRow.phoneNumbers) { try { const processedPhone = formatter.processPhoneNumber( phoneNumber, Encoding.HEX, ); userData.userIdentifiers.push( UserIdentifier.create({phoneNumber: processedPhone}), ); } catch (e) { console.warn(`Invalid phone: ${phoneNumber}. Skipping.`); } } } if (userData.userIdentifiers.length > 0) { event.userData = userData; } events.push(event); } // Sets up the Destination. const operatingAccountType = convertToAccountType( argv.operating_account_type, 'operating_account_type', ); const destination = Destination.create({ operatingAccount: ProductAccount.create({ accountType: operatingAccountType, accountId: argv.operating_account_id, }), productDestinationId: argv.conversion_action_id, }); // The login account is optional. if (argv.login_account_type) { const loginAccountType = convertToAccountType( argv.login_account_type, 'login_account_type', ); destination.loginAccount = ProductAccount.create({ accountType: loginAccountType, accountId: argv.login_account_id, }); } // The linked account is optional. if (argv.linked_account_type) { const linkedAccountType = convertToAccountType( argv.linked_account_type, 'linked_account_type', ); destination.linkedAccount = ProductAccount.create({ accountType: linkedAccountType, accountId: argv.linked_account_id, }); } const client = new IngestionServiceClient(); let requestCount = 0; // Batches requests to send up to the maximum number of events per request. for (let i = 0; i < events.length; i += MAX_EVENTS_PER_REQUEST) { requestCount++; const eventsBatch = events.slice(i, i + MAX_EVENTS_PER_REQUEST); // Builds the request. const request = IngestEventsRequest.create({ destinations: [destination], // Adds events from the current batch. events: eventsBatch, consent: Consent.create({ adUserData: ConsentStatus.CONSENT_GRANTED, adPersonalization: ConsentStatus.CONSENT_GRANTED, }), // Sets encoding to match the encoding used. encoding: DataManagerEncoding.HEX, // Sets validate_only. If true, then the Data Manager API only validates the request validateOnly: argv.validate_only, }); const [response] = await client.ingestEvents(request); console.log(`Response for request #${requestCount}:\n`, response); } console.log(`# of requests sent: ${requestCount}`); } /** * Reads the event data from the given JSON file. * @param {string} jsonFile The path to the JSON file. * @return {EventRow[]} An array of event data. */ function readEventDataFile(jsonFile: string): EventRow[] { const fileContent = fs.readFileSync(jsonFile, 'utf8'); return JSON.parse(fileContent); } /** * Validates that a given string is an enum value for the AccountType enum, and * if validation passes, returns the AccountType enum value. * @param proposedValue the name of an AccountType enum value * @param paramName the name of the parameter to use in the error message if validation fails * @returns {protos.google.ads.datamanager.v1.ProductAccount.AccountType} The corresponding enum value. * @throws {Error} If the string is not an AccountType enum value. */ function convertToAccountType( proposedValue: string, paramName: string, ): protos.google.ads.datamanager.v1.ProductAccount.AccountType { const AccountType = ProductAccount.AccountType; const accountTypeEnumNames = Object.keys(AccountType).filter(key => isNaN(Number(key)), ); if (!accountTypeEnumNames.includes(proposedValue)) { throw new Error(`Invalid ${paramName}: ${proposedValue}`); } return AccountType[proposedValue as keyof typeof AccountType]; } if (require.main === module) { main().catch(console.error); }
পিএইচপি
<?php // Copyright 2025 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * Sample of sending an IngestEventsRequest without encryption. */ require_once dirname(__DIR__, 1) . '/vendor/autoload.php'; use Google\Ads\DataManager\V1\AdIdentifiers; use Google\Ads\DataManager\V1\Client\IngestionServiceClient; use Google\Ads\DataManager\V1\Consent; use Google\Ads\DataManager\V1\ConsentStatus; use Google\Ads\DataManager\V1\Destination; use Google\Ads\DataManager\V1\Encoding as DataManagerEncoding; use Google\Ads\DataManager\V1\Event; use Google\Ads\DataManager\V1\EventSource; use Google\Ads\DataManager\V1\IngestEventsRequest; use Google\Ads\DataManager\V1\ProductAccount; use Google\Ads\DataManager\V1\ProductAccount\AccountType; use Google\Ads\DataManager\V1\UserData; use Google\Ads\DataManager\V1\UserIdentifier; use Google\Ads\DataManagerUtil\Encoding; use Google\Ads\DataManagerUtil\Formatter; use Google\ApiCore\ApiException; use Google\Protobuf\Timestamp; // The maximum number of events allowed per request. const MAX_EVENTS_PER_REQUEST = 2000; /** * Reads the JSON-formatted event data file. * * @param string $jsonFile The event data file. * @return array A list of associative arrays, each representing an event. */ function readEventDataFile(string $jsonFile): array { $jsonContent = file_get_contents($jsonFile); if ($jsonContent === false) { throw new \RuntimeException(sprintf('Could not read JSON file: %s', $jsonFile)); } $events = json_decode($jsonContent, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \RuntimeException(sprintf('Invalid JSON in file: %s', $jsonFile)); } return $events; } /** * Runs the sample. * * @param int $operatingAccountType The account type of the operating account. * @param string $operatingAccountId The ID of the operating account. * @param string $conversionActionId The ID of the conversion action. * @param string $jsonFile The JSON file containing event data. * @param bool $validateOnly Whether to enable validateOnly on the request. * @param int|null $loginAccountType The account type of the login account. * @param string|null $loginAccountId The ID of the login account. * @param int|null $linkedAccountType The account type of the linked account. * @param string|null $linkedAccountId The ID of the linked account. */ function main( int $operatingAccountType, string $operatingAccountId, string $conversionActionId, string $jsonFile, bool $validateOnly, ?int $loginAccountType = null, ?string $loginAccountId = null, ?int $linkedAccountType = null, ?string $linkedAccountId = null ): void { // Reads event data from the data file. $eventRecords = readEventDataFile($jsonFile); // Gets an instance of the UserDataFormatter for normalizing and formatting the data. $formatter = new Formatter(); // Builds the events collection for the request. $events = []; foreach ($eventRecords as $eventRecord) { $event = new Event(); if (empty($eventRecord['timestamp'])) { error_log('Skipping event with no timestamp.'); continue; } try { $dateTime = new DateTime($eventRecord['timestamp']); $timestamp = new Timestamp(); $timestamp->fromDateTime($dateTime); $event->setEventTimestamp($timestamp); } catch (\Exception $e) { error_log(sprintf('Skipping event with invalid timestamp: %s', $eventRecord['timestamp'])); continue; } if (empty($eventRecord['transactionId'])) { error_log('Skipping event with no transaction ID'); continue; } $event->setTransactionId($eventRecord['transactionId']); if (!empty($eventRecord['eventSource'])) { try { $event->setEventSource(EventSource::value($eventRecord['eventSource'])); } catch (\UnexpectedValueException $e) { error_log('Skipping event with invalid event source: ' . $eventRecord['eventSource']); continue; } } if (!empty($eventRecord['gclid'])) { $event->setAdIdentifiers((new AdIdentifiers())->setGclid($eventRecord['gclid'])); } if (!empty($eventRecord['currency'])) { $event->setCurrency($eventRecord['currency']); } if (isset($eventRecord['value'])) { $event->setConversionValue($eventRecord['value']); } $userData = new UserData(); $identifiers = []; if (!empty($eventRecord['emails'])) { foreach ($eventRecord['emails'] as $email) { try { $preparedEmail = $formatter->processEmailAddress($email, Encoding::Hex); $identifiers[] = (new UserIdentifier())->setEmailAddress($preparedEmail); } catch (\InvalidArgumentException $e) { // Skips invalid input. error_log(sprintf('Skipping invalid email: %s', $e->getMessage())); continue; } } } if (!empty($eventRecord['phoneNumbers'])) { foreach ($eventRecord['phoneNumbers'] as $phoneNumber) { try { $preparedPhoneNumber = $formatter->processPhoneNumber($phoneNumber, Encoding::Hex); $identifiers[] = (new UserIdentifier())->setPhoneNumber($preparedPhoneNumber); } catch (\InvalidArgumentException $e) { // Skips invalid input. error_log(sprintf('Skipping invalid phone number: %s', $e->getMessage())); continue; } } } if (!empty($identifiers)) { $userData->setUserIdentifiers($identifiers); $event->setUserData($userData); } $events[] = $event; } // Builds the destination for the request. $destination = (new Destination()) ->setOperatingAccount((new ProductAccount()) ->setAccountType($operatingAccountType) ->setAccountId($operatingAccountId)) ->setProductDestinationId($conversionActionId); if ($loginAccountType !== null && $loginAccountId !== null) { $destination->setLoginAccount((new ProductAccount()) ->setAccountType($loginAccountType) ->setAccountId($loginAccountId)); } if ($linkedAccountType !== null && $linkedAccountId !== null) { $destination->setLinkedAccount((new ProductAccount()) ->setAccountType($linkedAccountType) ->setAccountId($linkedAccountId)); } $client = new IngestionServiceClient(); try { $requestCount = 0; // Batches requests to send up to the maximum number of events per request. foreach (array_chunk($events, MAX_EVENTS_PER_REQUEST) as $eventsBatch) { $requestCount++; // Builds the request. $request = (new IngestEventsRequest()) ->setDestinations([$destination]) ->setEvents($eventsBatch) ->setConsent((new Consent()) ->setAdUserData(ConsentStatus::CONSENT_GRANTED) ->setAdPersonalization(ConsentStatus::CONSENT_GRANTED) ) ->setValidateOnly($validateOnly) ->setEncoding(DataManagerEncoding::HEX); echo "Request:\n" . json_encode(json_decode($request->serializeToJsonString()), JSON_PRETTY_PRINT) . "\n"; $response = $client->ingestEvents($request); echo "Response for request #{$requestCount}:\n" . json_encode(json_decode($response->serializeToJsonString()), JSON_PRETTY_PRINT) . "\n"; } echo "# of requests sent: {$requestCount}\n"; } catch (ApiException $e) { echo 'Error sending request: ' . $e->getMessage() . "\n"; } finally { $client->close(); } } // Command-line argument parsing $options = getopt( '', [ 'operating_account_type:', 'operating_account_id:', 'login_account_type::', 'login_account_id::', 'linked_account_type::', 'linked_account_id::', 'conversion_action_id:', 'json_file:', 'validate_only::' ] ); $operatingAccountType = $options['operating_account_type'] ?? null; $operatingAccountId = $options['operating_account_id'] ?? null; $conversionActionId = $options['conversion_action_id'] ?? null; $jsonFile = $options['json_file'] ?? null; // Only validates requests by default. $validateOnly = true; if (array_key_exists('validate_only', $options)) { $value = $options['validate_only']; // `getopt` with `::` returns boolean `false` if the option is passed without a value. if ($value === false || !in_array($value, ['true', 'false'], true)) { echo "Error: --validate_only requires a value of 'true' or 'false'.\n"; exit(1); } $validateOnly = ($value === 'true'); } if (empty($operatingAccountType) || empty($operatingAccountId) || empty($conversionActionId) || empty($jsonFile)) { echo 'Usage: php ingest_events.php ' . '--operating_account_type=<account_type> ' . '--operating_account_id=<account_id> ' . '--conversion_action_id=<conversion_action_id> ' . "--json_file=<path_to_json>\n" . 'Optional: --login_account_type=<account_type> --login_account_id=<account_id> ' . '--linked_account_type=<account_type> --linked_account_id=<account_id> ' . "--validate_only=<true|false>\n"; exit(1); } // Converts the operating account type string to an AccountType enum. $parsedOperatingAccountType = AccountType::value($operatingAccountType); if (isset($options['login_account_type']) != isset($options['login_account_id'])) { throw new \InvalidArgumentException( 'Must specify either both or neither of login account type and login account ID' ); } $parsedLoginAccountType = null; if (isset($options['login_account_type'])) { // Converts the login account type string to an AccountType enum. $parsedLoginAccountType = AccountType::value($options['login_account_type']); } if (isset($options['linked_account_type']) != isset($options['linked_account_id'])) { throw new \InvalidArgumentException( 'Must specify either both or neither of linked account type and linked account ID' ); } $parsedLinkedAccountType = null; if (isset($options['linked_account_type'])) { // Converts the linked account type string to an AccountType enum. $parsedLinkedAccountType = AccountType::value($options['linked_account_type']); } main( $parsedOperatingAccountType, $operatingAccountId, $conversionActionId, $jsonFile, $validateOnly, $parsedLoginAccountType, $options['login_account_id'] ?? null, $parsedLinkedAccountType, $options['linked_account_id'] ?? null );
পাইথন
#!/usr/bin/env python # Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """Sample of sending an IngestEventsRequest without encryption.""" import argparse import json import logging from typing import Any, Dict, List, Optional from google.ads import datamanager_v1 from google.ads.datamanager_util import Formatter from google.ads.datamanager_util.format import Encoding from google.protobuf.timestamp_pb2 import Timestamp _logger = logging.getLogger(__name__) # The maximum number of events allowed per request. _MAX_EVENTS_PER_REQUEST = 10_000 def main( operating_account_type: datamanager_v1.ProductAccount.AccountType, operating_account_id: str, conversion_action_id: str, json_file: str, validate_only: bool, login_account_type: Optional[ datamanager_v1.ProductAccount.AccountType ] = None, login_account_id: Optional[str] = None, linked_account_type: Optional[ datamanager_v1.ProductAccount.AccountType ] = None, linked_account_id: Optional[str] = None, ) -> None: """Runs the sample. Args: operating_account_type: the account type of the operating account. operating_account_id: the ID of the operating account. json_file: the JSON file containing event data. validate_only: whether to enable validate_only on the request. login_account_type: the account type of the login account. login_account_id: the ID of the login account. linked_account_type: the account type of the linked account. linked_account_id: the ID of the linked account. """ # Gets an instance of the formatter. formatter: Formatter = Formatter() # Reads the input file. event_rows: List[Dict[str, Any]] = read_event_data_file(json_file) events: List[datamanager_v1.Event] = [] for event_row in event_rows: event = datamanager_v1.Event() try: event_timestamp = Timestamp() event_timestamp.FromJsonString(str(event_row["timestamp"])) event.event_timestamp = event_timestamp except ValueError: _logger.warning( "Invalid timestamp format: %s. Skipping row.", event_row["timestamp"], ) continue if "transactionId" not in event_row: _logger.warning("Skipping event with no transaction ID") continue event.transaction_id = event_row["transactionId"] if "eventSource" in event_row: event.event_source = event_row["eventSource"] if "gclid" in event_row: event.ad_identifiers = datamanager_v1.AdIdentifiers( gclid=event_row["gclid"] ) if "currency" in event_row: event.currency = event_row["currency"] if "value" in event_row: event.conversion_value = event_row["value"] user_data = datamanager_v1.UserData() # Adds a UserIdentifier for each valid email address for the event row. if "emails" in event_row: for email in event_row["emails"]: try: processed_email: str = formatter.process_email_address( email, Encoding.HEX ) user_data.user_identifiers.append( datamanager_v1.UserIdentifier( email_address=processed_email ) ) except ValueError: # Skips invalid input. _logger.warning( "Invalid email address: %s. Skipping.", event_row["email_address"], ) # Adds a UserIdentifier for each valid phone number for the event row. if "phoneNumbers" in event_row: for phone_number in event_row["phoneNumbers"]: try: processed_phone: str = formatter.process_phone_number( phone_number, Encoding.HEX ) user_data.user_identifiers.append( datamanager_v1.UserIdentifier( phone_number=processed_phone ) ) except ValueError: # Skips invalid input. _logger.warning( "Invalid phone: %s. Skipping.", event_row["phone_number"], ) if user_data.user_identifiers: event.user_data = user_data # Adds the event to the list of events to send in the request. events.append(event) # Configures the destination. destination: datamanager_v1.Destination = datamanager_v1.Destination() destination.operating_account.account_type = operating_account_type destination.operating_account.account_id = operating_account_id destination.product_destination_id = str(conversion_action_id) if login_account_type or login_account_id: if bool(login_account_type) != bool(login_account_id): raise ValueError( "Must specify either both or neither of login " + "account type and login account ID" ) destination.login_account.account_type = login_account_type destination.login_account.account_id = login_account_id if linked_account_type or linked_account_id: if bool(linked_account_type) != bool(linked_account_id): raise ValueError( "Must specify either both or neither of linked account " + "type and linked account ID" ) destination.linked_account.account_type = linked_account_type destination.linked_account.account_id = linked_account_id # Creates a client for the ingestion service. client: datamanager_v1.IngestionServiceClient = ( datamanager_v1.IngestionServiceClient() ) # Batches requests to send up to the maximum number of events per # request. request_count = 0 for i in range(0, len(events), _MAX_EVENTS_PER_REQUEST): request_count += 1 events_batch = events[i : i + _MAX_EVENTS_PER_REQUEST] # Sends the request. request: datamanager_v1.IngestEventsRequest = ( datamanager_v1.IngestEventsRequest( destinations=[destination], # Adds events from the current batch. events=events_batch, consent=datamanager_v1.Consent( ad_user_data=datamanager_v1.ConsentStatus.CONSENT_GRANTED, ad_personalization=datamanager_v1.ConsentStatus.CONSENT_GRANTED, ), # Sets encoding to match the encoding used. encoding=datamanager_v1.Encoding.HEX, # Sets validate_only. If true, then the Data Manager API only # validates the request but doesn't apply changes. validate_only=validate_only, ) ) # Sends the request. response: datamanager_v1.IngestEventsResponse = client.ingest_events( request=request ) # Logs the response. _logger.info("Response for request #%d:\n%s", request_count, response) _logger.info("# of requests sent: %d", request_count) def read_event_data_file(json_file: str) -> List[Dict[str, Any]]: """Reads the JSON-formatted event data file. Args: json_file: the event data file. """ with open(json_file, "r") as f: return json.load(f) if __name__ == "__main__": # Configures logging. logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser( description=("Sends events from a JSON file to a destination."), fromfile_prefix_chars="@", ) # The following argument(s) should be provided to run the example. parser.add_argument( "--operating_account_type", type=str, required=True, help="The account type of the operating account.", ) parser.add_argument( "--operating_account_id", type=str, required=True, help="The ID of the operating account.", ) parser.add_argument( "--conversion_action_id", type=int, required=True, help="The ID of the conversion action", ) parser.add_argument( "--login_account_type", type=str, required=False, help="The account type of the login account.", ) parser.add_argument( "--login_account_id", type=str, required=False, help="The ID of the login account.", ) parser.add_argument( "--linked_account_type", type=str, required=False, help="The account type of the linked account.", ) parser.add_argument( "--linked_account_id", type=str, required=False, help="The ID of the linked account.", ) parser.add_argument( "--json_file", type=str, required=True, help="JSON file containing user data to ingest.", ) parser.add_argument( "--validate_only", choices=["true", "false"], default="true", help="""Whether to enable validate_only on the request. Must be 'true' or 'false'. Defaults to 'true'.""", ) args = parser.parse_args() main( args.operating_account_type, args.operating_account_id, args.conversion_action_id, args.json_file, args.validate_only == "true", args.login_account_type, args.login_account_id, args.linked_account_type, args.linked_account_id, )
Success responses
একটি সফল অনুরোধের ফলে একটি প্রতিক্রিয়া পাওয়া যায়, যাতে একটি অবজেক্ট থাকে এবং সেই অবজেক্টটিতে একটি requestId অন্তর্ভুক্ত থাকে।
{
"requestId": "126365e1-16d0-4c81-9de9-f362711e250a"
}
ফেরত আসা requestId টি রেকর্ড করে রাখুন, যাতে অনুরোধের প্রতিটি গন্তব্য প্রক্রিয়াকরণের সাথে সাথে আপনি ডায়াগনস্টিকস পুনরুদ্ধার করতে পারেন।
Failure responses
একটি ব্যর্থ অনুরোধের ফলে 400 Bad Request এর মতো একটি ত্রুটিপূর্ণ প্রতিক্রিয়া স্ট্যাটাস কোড এবং ত্রুটির বিবরণসহ একটি প্রতিক্রিয়া পাওয়া যায়।
উদাহরণস্বরূপ, হেক্স এনকোডেড মানের পরিবর্তে একটি সাধারণ টেক্সট স্ট্রিং সম্বলিত emailAddress ব্যবহার করলে নিম্নলিখিত প্রতিক্রিয়া তৈরি হয়:
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "events.events[0].user_data.user_identifiers",
"description": "Email is not hex encoded.",
"reason": "INVALID_HEX_ENCODING"
}
]
}
]
}
}
একটি emailAddress যা হ্যাশ করা হয়নি এবং শুধুমাত্র হেক্স এনকোড করা হয়েছে, তা নিম্নলিখিত প্রতিক্রিয়া তৈরি করে:
{
"error": {
"code": 400,
"message": "There was a problem with the request.",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "INVALID_ARGUMENT",
"domain": "datamanager.googleapis.com"
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "events.events[0]",
"reason": "INVALID_SHA256_FORMAT"
}
]
}
]
}
}
Send events for multiple destinations
আপনার ডেটাতে যদি বিভিন্ন গন্তব্যের ইভেন্ট থাকে, তাহলে আপনি ডেস্টিনেশন রেফারেন্স ব্যবহার করে সেগুলোকে একই অনুরোধে পাঠাতে পারেন। প্রতি অনুরোধে গন্তব্যের সর্বোচ্চ সংখ্যা জানতে ‘সীমা ও কোটা’ দেখুন।
উদাহরণস্বরূপ, যদি আপনার কনভার্সন অ্যাকশন আইডি 123456789 এর জন্য একটি ইভেন্ট এবং কনভার্সন অ্যাকশন আইডি 777111122 এর জন্য আরেকটি ইভেন্ট থাকে, তাহলে প্রতিটি Destination reference সেট করে উভয় ইভেন্ট একটিমাত্র রিকোয়েস্টে পাঠান। reference ব্যবহারকারী-নির্ধারিত। একমাত্র শর্ত হলো প্রতিটি Destination একটি অনন্য reference থাকতে হবে। রিকোয়েস্টটির জন্য পরিবর্তিত destinations তালিকাটি নিচে দেওয়া হলো:
বিজ্ঞাপনদাতা
"destinations": [
{
"operatingAccount": {
"accountType": "OPERATING_ACCOUNT_TYPE",
"accountId": "OPERATING_ACCOUNT_ID"
},
"loginAccount": {
"accountType": "LOGIN_ACCOUNT_TYPE",
"accountId": "LOGIN_ACCOUNT_ID"
},
"productDestinationId": "123456789",
"reference": "destination_a"
},
{
"operatingAccount": {
"accountType": "OPERATING_ACCOUNT_2_TYPE",
"accountId": "OPERATING_ACCOUNT_2_ID"
},
"loginAccount": {
"accountType": "LOGIN_ACCOUNT_2_TYPE",
"accountId": "LOGIN_ACCOUNT_2_ID"
},
"productDestinationId": "777111122",
"reference": "destination_b"
}
]
Data Partner
"destinations": [
{
"operatingAccount": {
"accountType": "OPERATING_ACCOUNT_TYPE",
"accountId": "OPERATING_ACCOUNT_ID"
},
"loginAccount": {
"accountType": "DATA_PARTNER",
"accountId": "DATA_PARTNER_ACCOUNT_ID"
},
"linkedAccount": {
"accountType": "LINKED_ACCOUNT_TYPE",
"accountId": "LINKED_ACCOUNT_ID"
},
"productDestinationId": "123456789",
"reference": "destination_a"
},
{
"operatingAccount": {
"accountType": "OPERATING_ACCOUNT_2_TYPE",
"accountId": "OPERATING_ACCOUNT_2_ID"
},
"loginAccount": {
"accountType": "DATA_PARTNER",
"accountId": "DATA_PARTNER_ACCOUNT_2_ID"
},
"linkedAccount": {
"accountType": "LINKED_ACCOUNT_2_TYPE",
"accountId": "LINKED_ACCOUNT_2_ID"
},
"productDestinationId": "777111122",
"reference": "destination_b"
}
]
প্রতিটি Event এক বা একাধিক নির্দিষ্ট গন্তব্যে পাঠানোর জন্য সেটির destinationReferences সেট করুন। উদাহরণস্বরূপ, এখানে একটি Event রয়েছে যা শুধুমাত্র প্রথম Destination জন্য, তাই এর destinationReferences তালিকায় কেবল প্রথম Destination reference রয়েছে:
{
"adIdentifiers": {
"gclid": "GCLID_1"
},
"conversionValue": 1.99,
"currency": "USD",
"eventTimestamp": "2025-06-10T20:07:01Z",
"transactionId": "ABC798654321",
"eventSource": "WEB",
"destinationReferences": [
"destination_a"
]
}
destinationReferences ফিল্ডটি একটি তালিকা, তাই আপনি একটি ইভেন্টের জন্য একাধিক গন্তব্য নির্দিষ্ট করতে পারেন। যদি আপনি কোনো Event destinationReferences সেট না করেন, তাহলে ডেটা ম্যানেজার এপিআই অনুরোধে থাকা সমস্ত গন্তব্যে ইভেন্টটি পাঠিয়ে দেয়।
যদি কোনো ইভেন্টের একাধিক গন্তব্য থাকে, তাহলে ডেটা ম্যানেজার এপিআই প্রতিটি গন্তব্যে প্রাসঙ্গিক ফিল্ডগুলো পাঠায়। উদাহরণস্বরূপ, যদি কোনো ইভেন্টের একটি গুগল অ্যাডস গন্তব্য এবং একটি গুগল অ্যানালিটিক্স গন্তব্য থাকে, তাহলে এপিআইটি ইভেন্টটিকে গুগল অ্যানালিটিক্স গন্তব্যে পাঠানোর সময় clientId , appInstanceId , বা eventName মতো গুগল অ্যানালিটিক্স ফিল্ডগুলো অন্তর্ভুক্ত করে এবং ইভেন্টটিকে গুগল অ্যাডস গন্তব্যে পাঠানোর সময় customVariables মতো গুগল অ্যাডস ফিল্ডগুলো অন্তর্ভুক্ত করে।
পরবর্তী পদক্ষেপ
- একটি ক্লায়েন্ট লাইব্রেরি ব্যবহার করে প্রমাণীকরণ কনফিগার করুন এবং আপনার পরিবেশ সেটআপ করুন।
- প্রতিটি ধরনের ডেটার জন্য প্রয়োজনীয় ফরম্যাটিং, হ্যাশিং এবং এনকোডিং সংক্রান্ত শর্তাবলী সম্পর্কে জানুন।
- Learn how to encrypt user data .
- আপনার অনুরোধগুলির জন্য ডায়াগনস্টিকস কীভাবে পুনরুদ্ধার করবেন তা জানুন।
- Learn about best practices .
- Learn about limits and quotas .