تطبیق مشتری به شما امکان میدهد از دادههای آنلاین و آفلاین خود برای دسترسی و تعامل مجدد با مشتریان خود در سراسر جستجو، تب خرید، جیمیل، یوتیوب و نمایش استفاده کنید. با استفاده از اطلاعاتی که مشتریان شما با شما به اشتراک گذاشتهاند، تطبیق مشتری تبلیغات را برای آن مشتریان و سایر مشتریان مانند آنها هدف قرار میدهد. میتوانید دادههای مدیریت ارتباط با مشتری (CRM) را به صورت عمده آپلود کنید، دادهها را اضافه یا حذف کنید، یا از این لیستهای کاربر برای ایجاد یک logical_user_list
استفاده کنید.
برای مشاهدهی فهرستی از انواع مختلف بخشهای مخاطب و مقایسهی تطبیق مشتری با سایر گزینههای فهرست کاربران، به نمای کلی مدیریت مخاطب مراجعه کنید.
درباره تطبیق مشتری و هدفگیری مخاطب بیشتر بدانید.
پیشنیازها
هر حسابی واجد شرایط استفاده از Customer Match نیست. برای استفاده از Customer Match، حساب شما باید موارد زیر را داشته باشد:
- سابقه خوب در رعایت سیاستها
- سابقه پرداخت خوب
بسته به اینکه حساب شما کدام الزامات را برآورده میکند، ویژگیهای مختلفی در دسترس هستند. برای اطلاع از شرایط و محدودیتهای واجد شرایط بودن، به سیاست تطبیق مشتری مراجعه کنید.
قبل از شروع: پیادهسازی خود را برنامهریزی کنید
قبل از شروع به نوشتن هر کدی، برنامهریزی برای پیادهسازی Customer Match بسیار مهم است. این بخش، فرآیند کلی و ملاحظات کلیدی را برای کمک به شما در طراحی یک یکپارچهسازی قوی تشریح میکند. پس از داشتن یک برنامه مشخص، میتوانید مراحل پیادهسازی را که در ادامه آمده است، ادامه دهید.
جریان استفاده
در اینجا روند پیشنهادی برای ایجاد و هدف قرار دادن لیست مشتریان آمده است:
یک لیست خالی از مشتریان ایجاد کنید.
یک
OfflineUserDataJob
ایجاد کنید. ایجاد یک job بزرگ بسیار کارآمدتر از ایجاد چندین job کوچکتر است.مطمئن شوید که فیلد
consent
customer_match_user_list_metadata
را در درخواستهایcreate
OfflineUserDataJob
خود پر کردهاید. برای درخواستهایremove
، نیازی به رضایت نیست. اگرconsent.ad_user_data
یاconsent.ad_personalization
مربوط به کار رویDENIED
تنظیم شده باشد، API مقدارOfflineUserDataJobError.CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS
را برمیگرداند.اگر کاربری رضایت خود را رد کرده باشد، میتوانید یک job با عملیات
remove
ایجاد کنید تا شناسههای کاربر را از لیست کاربران حذف کند.اگر رضایت کاربران خاصی را ندارید، یک کار جداگانه ایجاد کنید که در آن فیلد
consent
customer_match_user_list_metadata
کار را تنظیم نکرده باشید، سپس با استفاده از عملیاتcreate
برای آن کار جداگانه، شناسههایی را برای آن کاربران اضافه کنید.عملیات را با استفاده از متد
OfflineUserDataJobService.AddOfflineUserDataJobOperations
اضافه کنید. برای پردازش بهینه، توصیه میکنیم حداکثر ۱۰۰۰۰ شناسه را در یک فراخوانی واحد اضافه کنید. یک درخواستAddOfflineUserDataJobOperations
میتواند حداکثر ۱۰۰۰۰۰ شناسه را در تمام اشیاءUserData
در لیست عملیات داشته باشد.برای مثال، اگر هر یک از اشیاء
UserData
شما یکUserIdentifier
برایhashed_email
و یکUserIdentifier
دیگر برایhashed_phone_number
داشته باشد، ارسال ۵۰۰۰ شیءUserData
در هر درخواست بهینه است زیرا هر درخواست در مجموع شامل ۱۰۰۰۰ شناسه کاربر خواهد بود.مرحله قبل را تا زمانی که همه عملیات اضافه شوند یا تا زمانی که ظرفیت کار تکمیل شود، تکرار کنید. هیچ محدودیتی در تعداد عملیاتی که میتوانید به یک کار اضافه کنید وجود ندارد؛ با این حال، برای پردازش بهینه، توصیه میکنیم بیش از ۱،۰۰۰،۰۰۰ عملیات در هر کار نباشد.
کار را اجرا کنید. شما باید کار را ظرف ۵ روز از ایجاد آن اجرا کنید. در غیر این صورت، کار دیگر برای اجرا در دسترس نخواهد بود.
نظرسنجی برای آپلود موفقیتآمیز
نرخ تطابق را تأیید کنید.
لیست را هدف قرار دهید.
OfflineUserDataJobService و UserDataService
دو سرویس برای آپلود دادههای تطابق مشتری وجود دارد. سرویس را بر اساس مورد استفاده خود انتخاب کنید زیرا ممکن است محدودیتهایی برای یک سرویس وجود داشته باشد.
خدمات آپلود تطابق مشتری | |
---|---|
OfflineUserDataJobService (ترجیحی) | بیشتر توسعهدهندگان از این سرویس استفاده میکنند. این سرویس برای آپلودهای بزرگ با توان عملیاتی بالا بهینه شده است و پس از اتمام، معیارهای موفقیت را برمیگرداند. این راهنما در درجه اول بر روی این سرویس تمرکز دارد. |
UserDataService | این سرویس برای آپلود تعداد کمی شناسه در یک زمان با بهروزرسانیهای پراکنده بهینه شده است و برای اجرای مداوم بهینه نشده است. محدودیت 10 عملیات در هر درخواست را دارد. علاوه بر این، یک درخواست واحد نمیتواند در مجموع بیش از 100 مورد در تمام user_identifiers داشته باشد.برای راهنمایی در مورد آپلودها با این سرویس، به راهنمای مدیریت ادغام Customer Match خود مراجعه کنید. با شروع از نسخه v15 از API تبلیغات گوگل، باید فیلد |
بهترین شیوهها
هنگام طراحی یکپارچهسازی Customer Match خود، بهترین شیوههای زیر را در نظر داشته باشید:
سعی نکنید از چندین حساب برای تغییر یک لیست کاربری استفاده کنید. یک لیست کاربری فقط توسط حساب Google Ads یا حساب شریک دادهای که آن را ایجاد کرده است، قابل تغییر است.
برای جلوگیری از خطاهای
RESOURCE_EXHAUSTED
، تعداد عملیات به ازای هرAddOfflineUserDataJobOperationsRequest
را تا ۱۰۰۰۰۰ شناسه افزایش دهید.عملیات
create
وremove
را در یکOfflineUserDataJob
با هم ترکیب نکنید. انجام این کار میتواند منجر به خطایCONFLICTING_OPERATION
شود.فعال کردن
partial_failure
درAddOfflineUserDataJobOperationsRequest
برای شناسایی هرگونه عملیات مشکلساز قبل از اجرای کار. عملیات هنگام آپلود درOfflineUserDataJob
اعتبارسنجی میشوند.از اجرای همزمان چندین فرآیند
OfflineUserDataJob
که لیست کاربران یکسانی را تغییر میدهند (یعنی چندین job کهCustomerMatchUserListMetadata.user_list
آنها به یک نام منبع اشاره میکند) خودداری کنید. انجام این کار میتواند منجر به خطایCONCURRENT_MODIFICATION
شود زیرا چندین job مجاز به کار همزمان روی یک لیست نیستند. این خطا همچنین میتواند در صورت تلاش برای تغییر همزمان یک لیست از طریق رابط کاربری Google Ads و API Google Ads رخ دهد. توجه داشته باشید که این مورد در مورد افزودن عملیات به یک jobPENDING
صدق نمیکند، که میتواند در هر زمانی قبل از شروع job انجام شود.اگر هزاران عملیات برای اعمال دارید، یک
OfflineUserDataJob
ایجاد کنید که شامل تمام عملیات باشد. چندین job با تنها چند صد عملیات ایجاد نکنید و آنها را به صورت متوالی یا همزمان اجرا نکنید. یک job بزرگ با تمام عملیات شما بسیار کارآمدتر از چندین job کوچک است و احتمال مواجهه با خطا در گردش کار شما را کاهش میدهد.
برای ایدههایی در مورد چگونگی استفاده از فهرست مشتریان خود برای هدفگیری بهینه، به مرکز راهنمایی مراجعه کنید.
مرحله ۱: ایجاد لیست مشتریان
با استفاده از UserListService
یک لیست مشتری ایجاد کنید. لیستهای مشتری با تنظیم فیلد crm_based_user_list
در شیء user_list
ایجاد میشوند. فیلد crm_based_user_list
را میتوان روی انواع کمپینهایی که از لیستهای هدفگیری مشتری پشتیبانی میکنند، تنظیم کرد:
تطابق مشتری در انواع مختلف کمپین | |
---|---|
جستجوی شبکه | تبلیغات در شبکه جستجو نمایش داده میشوند. |
شبکه نمایش | تبلیغات در شبکه نمایش و در جیمیل فقط در صورتی نمایش داده میشوند که GSP خلاقیتهایی داشته باشد. |
نمایش گسترش در کمپینهای جستجو | تبلیغات در شبکه جستجو و در جیمیل فقط در صورتی نمایش داده میشوند که GSP وجود داشته باشد. |
کمپینهای ویدیویی | تبلیغات فقط در صورتی در یوتیوب نمایش داده میشوند که تبلیغات TrueView در حال پخش وجود داشته باشند. |
کمپینهای خرید | تبلیغات در برگه خرید نمایش داده میشوند. |
crm_based_user_list
شامل سه فیلد است:
app_id
: رشتهای که به طور منحصر به فرد برنامه تلفن همراهی را که دادهها از آن جمعآوری شدهاند، مشخص میکند. این مورد هنگام ایجادCrmBasedUserList
برای آپلود شناسههای تبلیغات تلفن همراه مورد نیاز است.upload_key_type
: نوع کلید منطبق با لیست، که میتواندCONTACT_INFO
،CRM_ID
یاMOBILE_ADVERTISING_ID
باشد. انواع دادههای ترکیبی در یک لیست مجاز نیستند. این فیلد برای همه لیستهای مشتریان الزامی است.data_source_type
: منبع داده لیست. مقدار پیشفرضFIRST_PARTY
است. مشتریان مجاز میتوانند لیستهای مشتری با منبع شخص ثالث ایجاد کنند.
ویژگی membership_life_span
در لیست کاربران به شما امکان میدهد دوره زمانی (بر حسب روز) را که یک کاربر در لیست در نظر گرفته میشود، تعریف کنید. membership_life_span
در لیست کاربران Customer Match نباید بیشتر از 540
باشد که مقدار پیشفرض نیز میباشد.
ویژگی membership_status
تعریف میکند که آیا لیست، کاربران جدید را میپذیرد یا خیر.
نمونه کد برای ایجاد لیست مشتریان
جاوا
private String createCustomerMatchUserList(GoogleAdsClient googleAdsClient, long customerId) { // Creates the new user list. UserList userList = UserList.newBuilder() .setName("Customer Match list #" + getPrintableDateTime()) .setDescription("A list of customers that originated from email addresses") // Membership life span must be between 0 and 540 days inclusive. See: // https://developers.google.com/google-ads/api/reference/rpc/latest/UserList#membership_life_span // Sets the membership life span to 30 days. .setMembershipLifeSpan(30) // Sets the upload key type to indicate the type of identifier that will be used to // add users to the list. This field is immutable and required for a CREATE operation. .setCrmBasedUserList( CrmBasedUserListInfo.newBuilder() .setUploadKeyType(CustomerMatchUploadKeyType.CONTACT_INFO)) .build(); // Creates the operation. UserListOperation operation = UserListOperation.newBuilder().setCreate(userList).build(); // Creates the service client. try (UserListServiceClient userListServiceClient = googleAdsClient.getLatestVersion().createUserListServiceClient()) { // Adds the user list. MutateUserListsResponse response = userListServiceClient.mutateUserLists( Long.toString(customerId), ImmutableList.of(operation)); // Prints the response. System.out.printf( "Created Customer Match user list with resource name: %s.%n", response.getResults(0).getResourceName()); return response.getResults(0).getResourceName(); } }
سی شارپ
private string CreateCustomerMatchUserList(GoogleAdsClient client, long customerId) { // Get the UserListService. UserListServiceClient service = client.GetService(Services.V22.UserListService); // Creates the user list. UserList userList = new UserList() { Name = $"Customer Match list# {ExampleUtilities.GetShortRandomString()}", Description = "A list of customers that originated from email and physical" + " addresses", // Membership life span must be between 0 and 540 days inclusive. See: // https://developers.google.com/google-ads/api/reference/rpc/latest/UserList#membership_life_span // Sets the membership life span to 30 days. MembershipLifeSpan = 30, CrmBasedUserList = new CrmBasedUserListInfo() { UploadKeyType = CustomerMatchUploadKeyType.ContactInfo } }; // Creates the user list operation. UserListOperation operation = new UserListOperation() { Create = userList }; // Issues a mutate request to add the user list and prints some information. MutateUserListsResponse response = service.MutateUserLists( customerId.ToString(), new[] { operation }); string userListResourceName = response.Results[0].ResourceName; Console.WriteLine($"User list with resource name '{userListResourceName}' " + $"was created."); return userListResourceName; }
پی اچ پی
private static function createCustomerMatchUserList( GoogleAdsClient $googleAdsClient, int $customerId ): string { // Creates the user list. $userList = new UserList([ 'name' => 'Customer Match list #' . Helper::getPrintableDatetime(), 'description' => 'A list of customers that originated from email ' . 'and physical addresses', // Membership life span must be between 0 and 540 days inclusive. See: // https://developers.google.com/google-ads/api/reference/rpc/latest/UserList#membership_life_span // Sets the membership life span to 30 days. 'membership_life_span' => 30, 'crm_based_user_list' => new CrmBasedUserListInfo([ // Sets the upload key type to indicate the type of identifier that will be used to // add users to the list. This field is immutable and required for a CREATE // operation. 'upload_key_type' => CustomerMatchUploadKeyType::CONTACT_INFO ]) ]); // Creates the user list operation. $operation = new UserListOperation(); $operation->setCreate($userList); // Issues a mutate request to add the user list and prints some information. $userListServiceClient = $googleAdsClient->getUserListServiceClient(); $response = $userListServiceClient->mutateUserLists( MutateUserListsRequest::build($customerId, [$operation]) ); $userListResourceName = $response->getResults()[0]->getResourceName(); printf("User list with resource name '%s' was created.%s", $userListResourceName, PHP_EOL); return $userListResourceName; }
پایتون
def create_customer_match_user_list( client: GoogleAdsClient, customer_id: str ) -> str: """Creates a Customer Match user list. Args: client: The Google Ads client. customer_id: The ID for the customer that owns the user list. Returns: The string resource name of the newly created user list. """ # Creates the UserListService client. user_list_service_client: UserListServiceClient = client.get_service( "UserListService" ) # Creates the user list operation. user_list_operation: UserListOperation = client.get_type( "UserListOperation" ) # Creates the new user list. user_list: UserList = user_list_operation.create user_list.name = f"Customer Match list #{uuid.uuid4()}" user_list.description = ( "A list of customers that originated from email and physical addresses" ) # Sets the upload key type to indicate the type of identifier that is used # to add users to the list. This field is immutable and required for a # CREATE operation. user_list.crm_based_user_list.upload_key_type = ( client.enums.CustomerMatchUploadKeyTypeEnum.CONTACT_INFO ) # Membership life span must be between 0 and 540 days inclusive. See: # https://developers.google.com/google-ads/api/reference/rpc/latest/UserList#membership_life_span # Sets the membership life span to 30 days. user_list.membership_life_span = 30 response: MutateUserListsResponse = ( user_list_service_client.mutate_user_lists( customer_id=customer_id, operations=[user_list_operation] ) ) user_list_resource_name: str = response.results[0].resource_name print( f"User list with resource name '{user_list_resource_name}' was created." ) return user_list_resource_name
روبی
def create_customer_match_user_list(client, customer_id) # Creates the user list. operation = client.operation.create_resource.user_list do |ul| ul.name = "Customer Match List #{(Time.new.to_f * 1000).to_i}" ul.description = "A list of customers that originated from email and " \ "physical addresses" # Membership life span must be between 0 and 540 days inclusive. See: # https://developers.google.com/google-ads/api/reference/rpc/latest/UserList#membership_life_span # Sets the membership life span to 30 days. ul.membership_life_span = 30 ul.crm_based_user_list = client.resource.crm_based_user_list_info do |crm| crm.upload_key_type = :CONTACT_INFO end end # Issues a mutate request to add the user list and prints some information. response = client.service.user_list.mutate_user_lists( customer_id: customer_id, operations: [operation], ) # Prints out some information about the newly created user list. resource_name = response.results.first.resource_name puts "User list with resource name #{resource_name} was created." resource_name end
پرل
sub create_customer_match_user_list { my ($api_client, $customer_id) = @_; # Create the user list. my $user_list = Google::Ads::GoogleAds::V22::Resources::UserList->new({ name => "Customer Match list #" . uniqid(), description => "A list of customers that originated from email and physical addresses", # Membership life span must be between 0 and 540 days inclusive. See: # https://developers.google.com/google-ads/api/reference/rpc/latest/UserList#membership_life_span # Set the membership life span to 30 days. membershipLifeSpan => 30, # Set the upload key type to indicate the type of identifier that will be # used to add users to the list. This field is immutable and required for # a CREATE operation. crmBasedUserList => Google::Ads::GoogleAds::V22::Common::CrmBasedUserListInfo->new({ uploadKeyType => CONTACT_INFO })}); # Create the user list operation. my $user_list_operation = Google::Ads::GoogleAds::V22::Services::UserListService::UserListOperation-> new({ create => $user_list }); # Issue a mutate request to add the user list and print some information. my $user_lists_response = $api_client->UserListService()->mutate({ customerId => $customer_id, operations => [$user_list_operation]}); my $user_list_resource_name = $user_lists_response->{results}[0]{resourceName}; printf "User list with resource name '%s' was created.\n", $user_list_resource_name; return $user_list_resource_name; }
مرحله ۲: اضافه کردن اعضا به لیست کاربران
سه کلید تطبیق اصلی عبارتند از آدرس ایمیل، آدرس پستی و شماره تلفن. میتوانید از شناسه کاربری و شناسه دستگاه تلفن همراه به عنوان کلیدهای تطبیق استفاده کنید، اما این راهحلها با توجه به وابستگیشان به کوکیها و شناسه دستگاه، در آینده چندان قابل اعتماد نیستند. توصیه میکنیم در صورت امکان، به جای شناسههای CRM یا تلفن همراه، اطلاعات تماس کاربر - مانند آدرس ایمیل، آدرس پستی و شماره تلفن - را بارگذاری کنید.
هر لیست کاربر فقط میتواند شامل یک نوع داده مشتری باشد که توسط فیلد CrmBasedUserListInfo.upload_key_type
مشخص شده است. علاوه بر این، یک شیء UserData
که نمایانگر یک کاربر واحد است، میتواند شامل حداکثر 20 شناسه کاربر باشد که هر کدام شیء UserIdentifier
مخصوص به خود را دارند. بیش از 20 شناسه منجر به خطای TOO_MANY_USER_IDENTIFIERS
میشود.
گوگل ادز فقط در صورتی از فهرست کاربران Customer Match برای هدفگیری استفاده میکند که در زمان نمایش تبلیغ، حداقل تعداد کاربران فعال را داشته باشد؛ کاربران فعال، تعداد کاربرانی در فهرست شما هستند که در Gmail، Search، YouTube یا Display فعال هستند. حداقل ۵۰۰۰ عضو آپلود کنید تا احتمال داشتن کاربران فعال و منطبق کافی برای هدفگیری افزایش یابد.
بارگذاری اطلاعات تماس کاربر
برای آپلود آدرسهای ایمیل، آدرسهای پستی یا شماره تلفنهای کاربر، upload_key_type
را روی CONTACT_INFO
تنظیم کنید. توجه داشته باشید که اطلاعات تماس برای تطبیق باید با یک حساب Google مرتبط باشند و حسابهای شرکتی - مانند Google Workspace - نمیتوانند هدف قرار گیرند.
برای حفظ حریم خصوصی، آدرسهای ایمیل، نام، نام خانوادگی و شماره تلفنها باید قبل از آپلود با استفاده از الگوریتم SHA-256 هش شوند. برای استانداردسازی نتایج هش، قبل از هش کردن یکی از این مقادیر، مطمئن شوید که کارهای زیر را انجام میدهید:
- فاصلههای خالیِ ابتدا و انتهای سطر را حذف کنید.
- برای نامها، آدرسهای ایمیل و آدرسهای پستی: متن را به حروف کوچک تبدیل کنید.
- برای شماره تلفنها: قبل از هش کردن، هر شماره تلفن را به فرمت E164 تبدیل کنید. این فرمت، شماره تلفن را به صورت عددی تا پانزده رقم که با علامت
+
شروع میشود، نشان میدهد - برای مثال،+12125650000
یا+442070313000
. علامت+
مقدم را میتوان به صورت اختیاری حذف کرد.
برای آدرسهای ایمیل، لازم نیست تمام نقطهها ( .
) قبل از نام دامنه را در آدرسهای ایمیل gmail.com
و googlemail.com
حذف کنید، زیرا آنها هنوز پذیرفته میشوند.
اگر اطلاعات تماس قبل از هش کردن به درستی قالببندی نشده باشد، API همچنان اطلاعات هش شده را میپذیرد، اما نمیتواند با مشتری مطابقت داده شود.
اگر میخواهید دادههای آدرس پستی را آپلود کنید، باید حداقل موارد زیر را وارد کنید:
- کد کشور
- کد پستی
- نام کوچک درهمریخته
- نام خانوادگی هش شده
اگر هر یک از این فیلدها وجود نداشته باشد، آدرس قابل تطبیق نیست.
در حالی که لیست مشتریان میتواند فقط شامل یک upload_key_type
باشد، میتوان چندین نوع اطلاعات تماس را برای upload_key_type
از CONTACT_INFO
آپلود کرد. این کار برای افزایش نرخ تطابق توصیه میشود.
بارگذاری شناسههای CRM
برای پر کردن لیست مشتریان با شناسههای CRM، upload_key_type
روی CRM_ID
تنظیم کنید. شناسههای CRM با شناسه کاربری تولید شده و اختصاص داده شده توسط تبلیغکننده مطابقت دارند. این مشابه آپلود نمونههای MOBILE_ADVERTISING_ID
است، اما شما به جای آن فیلد third_party_user_id
شیء UserIdentifier
پر میکنید.
بارگذاری مدارک شناسایی موبایل
مشابه تطبیق مشتری با ایمیل، میتوانید تطبیق مشتری را با استفاده از شناسههای دستگاه تلفن همراه شناسه برای تبلیغات (IDFA) یا شناسه تبلیغات گوگل (AAID) انجام دهید. برای انجام این کار، قبل از استفاده از لیست کاربران برای تطبیق مشتری با شناسههای دستگاه تلفن همراه، ویژگی app_id
را مشخص کرده و upload_key_type
روی MOBILE_ADVERTISING_ID
تنظیم کنید.
مثال کد
مثال زیر از یک OfflineUserDataJobOperation
برای افزودن اطلاعات تماس مشتری به لیست مشتریان استفاده میکند.
جاوا
// Creates a raw input list of unhashed user information, where each element of the list // represents a single user and is a map containing a separate entry for the keys "email", // "phone", "firstName", "lastName", "countryCode", and "postalCode". In your application, this // data might come from a file or a database. List<Map<String, String>> rawRecords = new ArrayList<>(); // The first user data has an email address and a phone number. Map<String, String> rawRecord1 = ImmutableMap.<String, String>builder() .put("email", "dana@example.com") // Phone number to be converted to E.164 format, with a leading '+' as required. This // includes whitespace that will be removed later. .put("phone", "+1 800 5550101") .build(); // The second user data has an email address, a mailing address, and a phone number. Map<String, String> rawRecord2 = ImmutableMap.<String, String>builder() // Email address that includes a period (.) before the domain. .put("email", "alex.2@example.com") // Address that includes all four required elements: first name, last name, country // code, and postal code. .put("firstName", "Alex") .put("lastName", "Quinn") .put("countryCode", "US") .put("postalCode", "94045") // Phone number to be converted to E.164 format, with a leading '+' as required. .put("phone", "+1 800 5550102") .build(); // The third user data only has an email address. Map<String, String> rawRecord3 = ImmutableMap.<String, String>builder().put("email", "charlie@example.com").build(); // Adds the raw records to the raw input list. rawRecords.add(rawRecord1); rawRecords.add(rawRecord2); rawRecords.add(rawRecord3); // Iterates over the raw input list and creates a UserData object for each record. List<UserData> userDataList = new ArrayList<>(); for (Map<String, String> rawRecord : rawRecords) { // Creates a builder for the UserData object that represents a member of the user list. UserData.Builder userDataBuilder = UserData.newBuilder(); // Checks if the record has email, phone, or address information, and adds a SEPARATE // UserIdentifier object for each one found. For example, a record with an email address and a // phone number will result in a UserData with two UserIdentifiers. // IMPORTANT: Since the identifier attribute of UserIdentifier // (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) is a // oneof // (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set only ONE of // hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, or addressInfo. Setting more // than one of these attributes on the same UserIdentifier will clear all the other members // of the oneof. For example, the following code is INCORRECT and will result in a // UserIdentifier with ONLY a hashedPhoneNumber. // // UserIdentifier incorrectlyPopulatedUserIdentifier = // UserIdentifier.newBuilder() // .setHashedEmail("...") // .setHashedPhoneNumber("...") // .build(); // // The separate 'if' statements below demonstrate the correct approach for creating a UserData // for a member with multiple UserIdentifiers. // Checks if the record has an email address, and if so, adds a UserIdentifier for it. if (rawRecord.containsKey("email")) { UserIdentifier hashedEmailIdentifier = UserIdentifier.newBuilder() .setHashedEmail(normalizeAndHash(sha256Digest, rawRecord.get("email"), true)) .build(); // Adds the hashed email identifier to the UserData object's list. userDataBuilder.addUserIdentifiers(hashedEmailIdentifier); } // Checks if the record has a phone number, and if so, adds a UserIdentifier for it. if (rawRecord.containsKey("phone")) { UserIdentifier hashedPhoneNumberIdentifier = UserIdentifier.newBuilder() .setHashedPhoneNumber(normalizeAndHash(sha256Digest, rawRecord.get("phone"), true)) .build(); // Adds the hashed phone number identifier to the UserData object's list. userDataBuilder.addUserIdentifiers(hashedPhoneNumberIdentifier); } // Checks if the record has all the required mailing address elements, and if so, adds a // UserIdentifier for the mailing address. if (rawRecord.containsKey("firstName")) { // Checks if the record contains all the other required elements of a mailing address. Set<String> missingAddressKeys = new HashSet<>(); for (String addressKey : new String[] {"lastName", "countryCode", "postalCode"}) { if (!rawRecord.containsKey(addressKey)) { missingAddressKeys.add(addressKey); } } if (!missingAddressKeys.isEmpty()) { System.out.printf( "Skipping addition of mailing address information because the following required keys" + " are missing: %s%n", missingAddressKeys); } else { // Creates an OfflineUserAddressInfo object that contains all the required elements of a // mailing address. OfflineUserAddressInfo addressInfo = OfflineUserAddressInfo.newBuilder() .setHashedFirstName( normalizeAndHash(sha256Digest, rawRecord.get("firstName"), false)) .setHashedLastName( normalizeAndHash(sha256Digest, rawRecord.get("lastName"), false)) .setCountryCode(rawRecord.get("countryCode")) .setPostalCode(rawRecord.get("postalCode")) .build(); UserIdentifier addressIdentifier = UserIdentifier.newBuilder().setAddressInfo(addressInfo).build(); // Adds the address identifier to the UserData object's list. userDataBuilder.addUserIdentifiers(addressIdentifier); } } if (!userDataBuilder.getUserIdentifiersList().isEmpty()) { // Builds the UserData and adds it to the list. userDataList.add(userDataBuilder.build()); } } // Creates the operations to add users. List<OfflineUserDataJobOperation> operations = new ArrayList<>(); for (UserData userData : userDataList) { operations.add(OfflineUserDataJobOperation.newBuilder().setCreate(userData).build()); }
سی شارپ
// Creates a raw input list of unhashed user information, where each element of the list // represents a single user and is a map containing a separate entry for the keys // "email", "phone", "firstName", "lastName", "countryCode", and "postalCode". // In your application, this data might come from a file or a database. List<Dictionary<string, string>> rawRecords = new List<Dictionary<string, string>>(); // The first user data has an email address and a phone number. Dictionary<string, string> rawRecord1 = new Dictionary<string, string>(); rawRecord1.Add("email", "dana@example.com"); // Phone number to be converted to E.164 format, with a leading '+' as required. // This includes whitespace that will be removed later. rawRecord1.Add("phone", "+1 800 5550101"); // The second user data has an email address, a mailing address, and a phone number. Dictionary<string, string> rawRecord2 = new Dictionary<string, string>(); // Email address that includes a period (.) before the Gmail domain. rawRecord2.Add("email", "alex.2@example.com"); // Address that includes all four required elements: first name, last name, country // code, and postal code. rawRecord2.Add("firstName", "Alex"); rawRecord2.Add("lastName", "Quinn"); rawRecord2.Add("countryCode", "US"); rawRecord2.Add("postalCode", "94045"); // Phone number to be converted to E.164 format, with a leading '+' as required. // This includes whitespace that will be removed later. rawRecord2.Add("phone", "+1 800 5550102"); // The third user data only has an email address. Dictionary<string, string> rawRecord3 = new Dictionary<string, string>(); rawRecord3.Add("email", "charlie@example.com"); // Adds the raw records to the raw input list. rawRecords.Add(rawRecord1); rawRecords.Add(rawRecord2); rawRecords.Add(rawRecord3); // Iterates over the raw input list and creates a UserData object for each record. List<UserData> userDataList = new List<UserData>(); foreach (Dictionary<string, string> rawRecord in rawRecords) { // Creates a UserData object that represents a member of the user list. UserData userData = new UserData(); // Checks if the record has email, phone, or address information, and adds a // SEPARATE UserIdentifier object for each one found. // For example, a record with an email address and a phone number will result in a // UserData with two UserIdentifiers. // IMPORTANT: Since the identifier attribute of UserIdentifier // (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) // is a oneof // (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set // only ONE of hashedEmail, hashedPhoneNumber, mobileId, thirdPartyUserId, // or addressInfo. // Setting more than one of these attributes on the same UserIdentifier will clear // all the other members of the oneof. // For example, the following code is INCORRECT and will result in a UserIdentifier // with ONLY a hashedPhoneNumber. // // UserIdentifier incorrectlyPopulatedUserIdentifier = new UserIdentifier() // { // HashedEmail = "...", // HashedPhoneNumber = "..." // }; // // The separate 'if' statements below demonstrate the correct approach for creating // a UserData for a member with multiple UserIdentifiers. // Checks if the record has an email address, and if so, adds a UserIdentifier // for it. if (rawRecord.ContainsKey("email")) { UserIdentifier hashedEmailIdentifier = new UserIdentifier() { HashedEmail = NormalizeAndHash(rawRecord["email"], true) }; userData.UserIdentifiers.Add(hashedEmailIdentifier); } // Checks if the record has a phone number, and if so, adds a UserIdentifier for it. if (rawRecord.ContainsKey("phone")) { UserIdentifier hashedPhoneNumberIdentifier = new UserIdentifier() { HashedPhoneNumber = NormalizeAndHash(rawRecord["phone"], true) }; // Adds the hashed phone number identifier to the UserData object's list. userData.UserIdentifiers.Add(hashedPhoneNumberIdentifier); } // Checks if the record has all the required mailing address elements, and if so, // adds a UserIdentifier for the mailing address. if (rawRecord.ContainsKey("firstName")) { // Checks if the record contains all the other required elements of a mailing // address. HashSet<string> missingAddressKeys = new HashSet<string>(); foreach (string addressKey in new string[] {"lastName", "countryCode", "postalCode"}) { if (!rawRecord.ContainsKey(addressKey)) { missingAddressKeys.Add(addressKey); } } if (!missingAddressKeys.Any()) { Console.WriteLine( $"Skipping addition of mailing address information because the following " + "required keys are missing: {missingAddressKeys}"); } else { // Creates an OfflineUserAddressInfo object that contains all the required // elements of a mailing address. OfflineUserAddressInfo addressInfo = new OfflineUserAddressInfo() { HashedFirstName = NormalizeAndHash(rawRecord["firstName"]), HashedLastName = NormalizeAndHash(rawRecord["lastName"]), CountryCode = rawRecord["countryCode"], PostalCode = rawRecord["postalCode"] }; UserIdentifier addressIdentifier = new UserIdentifier() { AddressInfo = addressInfo }; // Adds the address identifier to the UserData object's list. userData.UserIdentifiers.Add(addressIdentifier); } } if (userData.UserIdentifiers.Any()) { userDataList.Add(userData); } } // Creates the operations to add the users. List<OfflineUserDataJobOperation> operations = new List<OfflineUserDataJobOperation>(); foreach(UserData userData in userDataList) { operations.Add(new OfflineUserDataJobOperation() { Create = userData }); }
پی اچ پی
// Creates a raw input list of unhashed user information, where each element of the list // represents a single user and is a map containing a separate entry for the keys 'email', // 'phone', 'firstName', 'lastName', 'countryCode', and 'postalCode'. In your application, // this data might come from a file or a database. $rawRecords = []; // The first user data has an email address and a phone number. $rawRecord1 = [ // The first user data has an email address and a phone number. 'email' => 'dana@example.com', // Phone number to be converted to E.164 format, with a leading '+' as required. This // includes whitespace that will be removed later. 'phone' => '+1 800 5550101' ]; $rawRecords[] = $rawRecord1; // The second user data has an email address, a mailing address, and a phone number. $rawRecord2 = [ // Email address that includes a period (.) before the Gmail domain. 'email' => 'alex.2@example.com', // Address that includes all four required elements: first name, last name, country // code, and postal code. 'firstName' => 'Alex', 'lastName' => 'Quinn', 'countryCode' => 'US', 'postalCode' => '94045', // Phone number to be converted to E.164 format, with a leading '+' as required. 'phone' => '+1 800 5550102', ]; $rawRecords[] = $rawRecord2; // The third user data only has an email address. $rawRecord3 = ['email' => 'charlie@example.com']; $rawRecords[] = $rawRecord3; // Iterates over the raw input list and creates a UserData object for each record. $userDataList = []; foreach ($rawRecords as $rawRecord) { // Checks if the record has email, phone, or address information, and adds a SEPARATE // UserIdentifier object for each one found. For example, a record with an email address // and a phone number will result in a UserData with two UserIdentifiers. // IMPORTANT: Since the identifier attribute of UserIdentifier // (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) is // a oneof // (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set only // ONE of 'hashed_email, 'hashed_phone_number', 'mobile_id', 'third_party_user_id', or // 'address_info'. // Setting more than one of these attributes on the same UserIdentifier will clear all // the other members of the oneof. For example, the following code is INCORRECT and will // result in a UserIdentifier with ONLY a 'hashed_phone_number'. // // $incorrectlyPopulatedUserIdentifier = new UserIdentifier(); // $incorrectlyPopulatedUserIdentifier->setHashedEmail('...'); // $incorrectlyPopulatedUserIdentifier->setHashedPhoneNumber('...'); // // The separate 'if' statements below demonstrate the correct approach for creating a // UserData for a member with multiple UserIdentifiers. $userIdentifiers = []; // Checks if the record has an email address, and if so, adds a UserIdentifier for it. if (array_key_exists('email', $rawRecord)) { $hashedEmailIdentifier = new UserIdentifier([ 'hashed_email' => self::normalizeAndHash($rawRecord['email'], true) ]); // Adds the hashed email identifier to the user identifiers list. $userIdentifiers[] = $hashedEmailIdentifier; } // Checks if the record has a phone number, and if so, adds a UserIdentifier for it. if (array_key_exists('phone', $rawRecord)) { $hashedPhoneNumberIdentifier = new UserIdentifier([ 'hashed_phone_number' => self::normalizeAndHash($rawRecord['phone'], true) ]); // Adds the hashed email identifier to the user identifiers list. $userIdentifiers[] = $hashedPhoneNumberIdentifier; } // Checks if the record has all the required mailing address elements, and if so, adds a // UserIdentifier for the mailing address. if (array_key_exists('firstName', $rawRecord)) { // Checks if the record contains all the other required elements of a mailing // address. $missingAddressKeys = []; foreach (['lastName', 'countryCode', 'postalCode'] as $addressKey) { if (!array_key_exists($addressKey, $rawRecord)) { $missingAddressKeys[] = $addressKey; } } if (!empty($missingAddressKeys)) { printf( "Skipping addition of mailing address information because the " . "following required keys are missing: %s%s", json_encode($missingAddressKeys), PHP_EOL ); } else { // Creates an OfflineUserAddressInfo object that contains all the required // elements of a mailing address. $addressIdentifier = new UserIdentifier([ 'address_info' => new OfflineUserAddressInfo([ 'hashed_first_name' => self::normalizeAndHash( $rawRecord['firstName'], false ), 'hashed_last_name' => self::normalizeAndHash( $rawRecord['lastName'], false ), 'country_code' => $rawRecord['countryCode'], 'postal_code' => $rawRecord['postalCode'] ]) ]); // Adds the address identifier to the user identifiers list. $userIdentifiers[] = $addressIdentifier; } } if (!empty($userIdentifiers)) { // Builds the UserData and adds it to the list. $userDataList[] = new UserData(['user_identifiers' => $userIdentifiers]); } } // Creates the operations to add users. $operations = array_map( function (UserData $userData) { return new OfflineUserDataJobOperation(['create' => $userData]); }, $userDataList );
پایتون
def build_offline_user_data_job_operations( client: GoogleAdsClient, ) -> List[OfflineUserDataJobOperation]: """Creates a raw input list of unhashed user information. Each element of the list represents a single user and is a dict containing a separate entry for the keys "email", "phone", "first_name", "last_name", "country_code", and "postal_code". In your application, this data might come from a file or a database. Args: client: The Google Ads client. Returns: A list containing the operations. """ # The first user data has an email address and a phone number. raw_record_1: Dict[str, str] = { "email": "dana@example.com", # Phone number to be converted to E.164 format, with a leading '+' as # required. This includes whitespace that will be removed later. "phone": "+1 800 5550101", } # The second user data has an email address, a mailing address, and a phone # number. raw_record_2: Dict[str, str] = { # Email address that includes a period (.) before the email domain. "email": "alex.2@example.com", # Address that includes all four required elements: first name, last # name, country code, and postal code. "first_name": "Alex", "last_name": "Quinn", "country_code": "US", "postal_code": "94045", # Phone number to be converted to E.164 format, with a leading '+' as # required. "phone": "+1 800 5550102", } # The third user data only has an email address. raw_record_3: Dict[str, str] = {"email": "charlie@example.com"} # Adds the raw records to a raw input list. raw_records: List[Dict[str, str]] = [ raw_record_1, raw_record_2, raw_record_3, ] operations: List[OfflineUserDataJobOperation] = [] # Iterates over the raw input list and creates a UserData object for each # record. for record in raw_records: # Creates a UserData object that represents a member of the user list. user_data: UserData = client.get_type("UserData") # Checks if the record has email, phone, or address information, and # adds a SEPARATE UserIdentifier object for each one found. For example, # a record with an email address and a phone number will result in a # UserData with two UserIdentifiers. # IMPORTANT: Since the identifier attribute of UserIdentifier # (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) # is a oneof # (https://protobuf.dev/programming-guides/proto3/#oneof-features), you # must set only ONE of hashed_email, hashed_phone_number, mobile_id, # third_party_user_id, or address-info. Setting more than one of these # attributes on the same UserIdentifier will clear all the other members # of the oneof. For example, the following code is INCORRECT and will # result in a UserIdentifier with ONLY a hashed_phone_number: # incorrect_user_identifier = client.get_type("UserIdentifier") # incorrect_user_identifier.hashed_email = "..." # incorrect_user_identifier.hashed_phone_number = "..." # The separate 'if' statements below demonstrate the correct approach # for creating a UserData object for a member with multiple # UserIdentifiers. # Checks if the record has an email address, and if so, adds a # UserIdentifier for it. if "email" in record: user_identifier: UserIdentifier = client.get_type("UserIdentifier") user_identifier.hashed_email = normalize_and_hash( record["email"], True ) # Adds the hashed email identifier to the UserData object's list. user_data.user_identifiers.append(user_identifier) # Checks if the record has a phone number, and if so, adds a # UserIdentifier for it. if "phone" in record: user_identifier: UserIdentifier = client.get_type("UserIdentifier") user_identifier.hashed_phone_number = normalize_and_hash( record["phone"], True ) # Adds the hashed phone number identifier to the UserData object's # list. user_data.user_identifiers.append(user_identifier) # Checks if the record has all the required mailing address elements, # and if so, adds a UserIdentifier for the mailing address. if "first_name" in record: required_keys = ("last_name", "country_code", "postal_code") # Checks if the record contains all the other required elements of # a mailing address. if not all(key in record for key in required_keys): # Determines which required elements are missing from the # record. missing_keys = record.keys() - required_keys print( "Skipping addition of mailing address information " "because the following required keys are missing: " f"{missing_keys}" ) else: user_identifier: UserIdentifier = client.get_type( "UserIdentifier" ) address_info: AddressInfo = user_identifier.address_info address_info.hashed_first_name = normalize_and_hash( record["first_name"], False ) address_info.hashed_last_name = normalize_and_hash( record["last_name"], False ) address_info.country_code = record["country_code"] address_info.postal_code = record["postal_code"] user_data.user_identifiers.append(user_identifier) # If the user_identifiers repeated field is not empty, create a new # OfflineUserDataJobOperation and add the UserData to it. if user_data.user_identifiers: operation: OfflineUserDataJobOperation = client.get_type( "OfflineUserDataJobOperation" ) operation.create = user_data operations.append(operation)
روبی
# Create a list of unhashed user data records that we will format in the # following steps to prepare for the API. raw_records = [ # The first user data has an email address and a phone number. { email: 'dana@example.com', # Phone number to be converted to E.164 format, with a leading '+' as # required. This includes whitespace that will be removed later. phone: '+1 800 5550100', }, # The second user data has an email address, a phone number, and an address. { # Email address that includes a period (.) before the Gmail domain. email: 'alex.2@example.com', # Address that includes all four required elements: first name, last # name, country code, and postal code. first_name: 'Alex', last_name: 'Quinn', country_code: 'US', postal_code: '94045', # Phone number to be converted to E.164 format, with a leading '+' as # required. phone: '+1 800 5550102', }, # The third user data only has an email address. { email: 'charlie@example.com', }, ] # Create a UserData for each entry in the raw records. user_data_list = raw_records.map do |record| client.resource.user_data do |data| if record[:email] data.user_identifiers << client.resource.user_identifier do |ui| ui.hashed_email = normalize_and_hash(record[:email], true) end end if record[:phone] data.user_identifiers << client.resource.user_identifier do |ui| ui.hashed_phone_number = normalize_and_hash(record[:phone], true) end end if record[:first_name] # Check that we have all the required information. missing_keys = [:last_name, :country_code, :postal_code].reject {|key| record[key].nil? } if missing_keys.empty? # If nothing is missing, add the address. data.user_identifiers << client.resource.user_identifier do |ui| ui.address_identifier = client.resource.offline_user_address_info do |address| address.hashed_first_name = normalize_and_hash(record[:first_name]) address.hashed_last_name = normalize_and_hash(record[:last_name]) address.country_code = record[:country_code] address.postal_code = record[:postal_code] end end else # If some data is missing, skip this entry. puts "Skipping addition of mailing information because the following keys are missing:" \ "#{missing_keys}" end end end end operations = user_data_list.map do |user_data| client.operation.create_resource.offline_user_data_job(user_data) end
پرل
# The first user data has an email address and a phone number. my $raw_record_1 = { email => 'dana@example.com', # Phone number to be converted to E.164 format, with a leading '+' as # required. This includes whitespace that will be removed later. phone => '+1 800 5550101', }; # The second user data has an email address, a mailing address, and a phone # number. my $raw_record_2 = { # Email address that includes a period (.) before the Gmail domain. email => 'alex.2@example.com', # Address that includes all four required elements: first name, last # name, country code, and postal code. firstName => 'Alex', lastName => 'Quinn', countryCode => 'US', postalCode => '94045', # Phone number to be converted to E.164 format, with a leading '+' as # required. phone => '+1 800 5550102', }; # The third user data only has an email address. my $raw_record_3 = {email => 'charlie@example.com',}; my $raw_records = [$raw_record_1, $raw_record_2, $raw_record_3]; my $operations = []; foreach my $record (@$raw_records) { # Check if the record has email, phone, or address information, and adds a # SEPARATE UserIdentifier object for each one found. For example, a record # with an email address and a phone number will result in a UserData with two # UserIdentifiers. # # IMPORTANT: Since the identifier attribute of UserIdentifier # (https://developers.google.com/google-ads/api/reference/rpc/latest/UserIdentifier) # is a oneof # (https://protobuf.dev/programming-guides/proto3/#oneof-features), you must set # only ONE of hashed_email, hashed_phone_number, mobile_id, third_party_user_id, # or address-info. Setting more than one of these attributes on the same UserIdentifier # will clear all the other members of the oneof. For example, the following code is # INCORRECT and will result in a UserIdentifier with ONLY a hashed_phone_number: # # my $incorrect_user_identifier = Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({ # hashedEmail => '...', # hashedPhoneNumber => '...', # }); # # The separate 'if' statements below demonstrate the correct approach for creating a # UserData object for a member with multiple UserIdentifiers. my $user_identifiers = []; # Check if the record has an email address, and if so, add a UserIdentifier for it. if (defined $record->{email}) { # Add the hashed email identifier to the list of UserIdentifiers. push( @$user_identifiers, Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({ hashedEmail => normalize_and_hash($record->{email}, 1)})); } # Check if the record has a phone number, and if so, add a UserIdentifier for it. if (defined $record->{phone}) { # Add the hashed phone number identifier to the list of UserIdentifiers. push( @$user_identifiers, Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({ hashedPhoneNumber => normalize_and_hash($record->{phone}, 1)})); } # Check if the record has all the required mailing address elements, and if so, add # a UserIdentifier for the mailing address. if (defined $record->{firstName}) { my $required_keys = ["lastName", "countryCode", "postalCode"]; my $missing_keys = []; foreach my $key (@$required_keys) { if (!defined $record->{$key}) { push(@$missing_keys, $key); } } if (@$missing_keys) { print "Skipping addition of mailing address information because the following" . "keys are missing: " . join(",", @$missing_keys); } else { push( @$user_identifiers, Google::Ads::GoogleAds::V22::Common::UserIdentifier->new({ addressInfo => Google::Ads::GoogleAds::V22::Common::OfflineUserAddressInfo-> new({ # First and last name must be normalized and hashed. hashedFirstName => normalize_and_hash($record->{firstName}), hashedLastName => normalize_and_hash($record->{lastName}), # Country code and zip code are sent in plain text. countryCode => $record->{countryCode}, postalCode => $record->{postalCode}, })})); } } # If the user_identifiers array is not empty, create a new # OfflineUserDataJobOperation and add the UserData to it. if (@$user_identifiers) { my $user_data = Google::Ads::GoogleAds::V22::Common::UserData->new({ userIdentifiers => [$user_identifiers]}); push( @$operations, Google::Ads::GoogleAds::V22::Services::OfflineUserDataJobService::OfflineUserDataJobOperation ->new({ create => $user_data })); } }
مرحله ۳: تأیید بارگذاری لیست و نرخ تطابق
زمانی که OfflineUserDataJob
وضعیت SUCCESS
داشته باشد، نرخ تطابق تخمینی در فیلد operation_metadata.match_rate_range
موجود است. اگر قبل از اتمام کار، از این فیلد کوئری بگیرید، مقدار این فیلد ممکن است صفر باشد. برای اطمینان از اینکه نرخ تطابق شما برای تأیید آماده است و لیست برای هدفگیری آماده است، توصیه میکنیم کار را برای تکمیل، نمونهبرداری (polling) کنید. تکمیل کار میتواند حداقل ۱۰ دقیقه یا حداکثر ۲۴ ساعت طول بکشد.
مثال کد برای بررسی وضعیت کار
جاوا
private void checkJobStatus( GoogleAdsClient googleAdsClient, long customerId, String offlineUserDataJobResourceName) { try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { String query = String.format( "SELECT offline_user_data_job.resource_name, " + "offline_user_data_job.id, " + "offline_user_data_job.status, " + "offline_user_data_job.type, " + "offline_user_data_job.failure_reason, " + "offline_user_data_job.customer_match_user_list_metadata.user_list " + "FROM offline_user_data_job " + "WHERE offline_user_data_job.resource_name = '%s'", offlineUserDataJobResourceName); // Issues the query and gets the GoogleAdsRow containing the job from the response. GoogleAdsRow googleAdsRow = googleAdsServiceClient .search(Long.toString(customerId), query) .iterateAll() .iterator() .next(); OfflineUserDataJob offlineUserDataJob = googleAdsRow.getOfflineUserDataJob(); System.out.printf( "Offline user data job ID %d with type '%s' has status: %s%n", offlineUserDataJob.getId(), offlineUserDataJob.getType(), offlineUserDataJob.getStatus()); OfflineUserDataJobStatus jobStatus = offlineUserDataJob.getStatus(); if (OfflineUserDataJobStatus.SUCCESS == jobStatus) { // Prints information about the user list. printCustomerMatchUserListInfo( googleAdsClient, customerId, offlineUserDataJob.getCustomerMatchUserListMetadata().getUserList()); } else if (OfflineUserDataJobStatus.FAILED == jobStatus) { System.out.printf(" Failure reason: %s%n", offlineUserDataJob.getFailureReason()); } else if (OfflineUserDataJobStatus.PENDING == jobStatus || OfflineUserDataJobStatus.RUNNING == jobStatus) { System.out.println(); System.out.printf( "To check the status of the job periodically, use the following GAQL query with" + " GoogleAdsService.search:%n%s%n", query); } } }
سی شارپ
private static void CheckJobStatusAndPrintResults(GoogleAdsClient client, long customerId, string offlineUserDataJobResourceName) { // Get the GoogleAdsService. GoogleAdsServiceClient service = client.GetService(Services.V22.GoogleAdsService); string query = "SELECT offline_user_data_job.resource_name, " + "offline_user_data_job.id, offline_user_data_job.status, " + "offline_user_data_job.type, offline_user_data_job.failure_reason, " + "offline_user_data_job.customer_match_user_list_metadata.user_list " + "FROM offline_user_data_job WHERE " + $"offline_user_data_job.resource_name = '{offlineUserDataJobResourceName}'"; // Issues the query and gets the GoogleAdsRow containing the job from the response. GoogleAdsRow googleAdsRow = service.Search(customerId.ToString(), query).First(); OfflineUserDataJob offlineUserDataJob = googleAdsRow.OfflineUserDataJob; Console.WriteLine($"Offline user data job ID {offlineUserDataJob.Id} with type " + $"'{offlineUserDataJob.Type}' has status: {offlineUserDataJob.Status}"); switch (offlineUserDataJob.Status) { case OfflineUserDataJobStatus.Success: // Prints information about the user list. PrintCustomerMatchUserListInfo(client, customerId, offlineUserDataJob.CustomerMatchUserListMetadata.UserList); break; case OfflineUserDataJobStatus.Failed: Console.WriteLine($" Failure reason: {offlineUserDataJob.FailureReason}"); break; case OfflineUserDataJobStatus.Pending: case OfflineUserDataJobStatus.Running: Console.WriteLine("To check the status of the job periodically, use the " + $"following GAQL query with GoogleAdsService.search:\n\n{query}"); break; } }
پی اچ پی
private static function checkJobStatus( GoogleAdsClient $googleAdsClient, int $customerId, string $offlineUserDataJobResourceName ) { $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves the offline user data job. $query = "SELECT offline_user_data_job.resource_name, " . "offline_user_data_job.id, " . "offline_user_data_job.status, " . "offline_user_data_job.type, " . "offline_user_data_job.failure_reason, " . "offline_user_data_job.customer_match_user_list_metadata.user_list " . "FROM offline_user_data_job " . "WHERE offline_user_data_job.resource_name = '$offlineUserDataJobResourceName'"; // Issues a search request to get the GoogleAdsRow containing the job from the response. /** @var GoogleAdsRow $googleAdsRow */ $googleAdsRow = $googleAdsServiceClient->search(SearchGoogleAdsRequest::build($customerId, $query)) ->getIterator() ->current(); $offlineUserDataJob = $googleAdsRow->getOfflineUserDataJob(); // Prints out some information about the offline user data job. $offlineUserDataJobStatus = $offlineUserDataJob->getStatus(); printf( "Offline user data job ID %d with type '%s' has status: %s.%s", $offlineUserDataJob->getId(), OfflineUserDataJobType::name($offlineUserDataJob->getType()), OfflineUserDataJobStatus::name($offlineUserDataJobStatus), PHP_EOL ); if ($offlineUserDataJobStatus === OfflineUserDataJobStatus::SUCCESS) { // Prints information about the user list. self::printCustomerMatchUserListInfo( $googleAdsClient, $customerId, $offlineUserDataJob->getCustomerMatchUserListMetadata()->getUserList() ); } elseif ($offlineUserDataJobStatus === OfflineUserDataJobStatus::FAILED) { printf(" Failure reason: %s.%s", $offlineUserDataJob->getFailureReason(), PHP_EOL); } elseif ( $offlineUserDataJobStatus === OfflineUserDataJobStatus::PENDING || $offlineUserDataJobStatus === OfflineUserDataJobStatus::RUNNING ) { printf( '%1$sTo check the status of the job periodically, use the following GAQL query with' . ' GoogleAdsService.search:%1$s%2$s%1$s', PHP_EOL, $query ); } }
پایتون
def check_job_status( client: GoogleAdsClient, customer_id: str, offline_user_data_job_resource_name: str, ) -> None: """Retrieves, checks, and prints the status of the offline user data job. If the job is completed successfully, information about the user list is printed. Otherwise, a GAQL query will be printed, which can be used to check the job status at a later date. Offline user data jobs may take 6 hours or more to complete, so checking the status periodically, instead of waiting, can be more efficient. Args: client: The Google Ads client. customer_id: The ID for the customer that owns the user list. offline_user_data_job_resource_name: The resource name of the offline user data job to get the status of. """ query: str = f""" SELECT offline_user_data_job.resource_name, offline_user_data_job.id, offline_user_data_job.status, offline_user_data_job.type, offline_user_data_job.failure_reason, offline_user_data_job.customer_match_user_list_metadata.user_list FROM offline_user_data_job WHERE offline_user_data_job.resource_name = '{offline_user_data_job_resource_name}' LIMIT 1""" # Issues a search request using streaming. google_ads_service: GoogleAdsServiceClient = client.get_service( "GoogleAdsService" ) results: SearchGoogleAdsStreamResponse = google_ads_service.search( customer_id=customer_id, query=query ) offline_user_data_job_result: OfflineUserDataJob = next( iter(results) ).offline_user_data_job status_name: str = offline_user_data_job_result.status.name user_list_resource_name: str = ( offline_user_data_job_result.customer_match_user_list_metadata.user_list ) print( f"Offline user data job ID '{offline_user_data_job_result.id}' with type " f"'{offline_user_data_job_result.type_.name}' has status: {status_name}" ) if status_name == "SUCCESS": print_customer_match_user_list_info( client, customer_id, user_list_resource_name ) elif status_name == "FAILED": print( f"\tFailure Reason: {offline_user_data_job_result.failure_reason}" ) elif status_name in ("PENDING", "RUNNING"): print( "To check the status of the job periodically, use the following " f"GAQL query with GoogleAdsService.Search: {query}" )
روبی
def check_job_status(client, customer_id, offline_user_data_job) query = <<~QUERY SELECT offline_user_data_job.id, offline_user_data_job.status, offline_user_data_job.type, offline_user_data_job.failure_reason, offline_user_data_job.customer_match_user_list_metadata.user_list FROM offline_user_data_job WHERE offline_user_data_job.resource_name = '#{offline_user_data_job}' QUERY row = client.service.google_ads.search( customer_id: customer_id, query: query, ).first job = row.offline_user_data_job puts "Offline user data job ID #{job.id} with type '#{job.type}' has status: #{job.status}." case job.status when :SUCCESS print_customer_match_user_list(client, customer_id, job.customer_match_user_list_metadata.user_list) when :FAILED puts " Failure reason: #{job.failure_reason}" else puts " To check the status of the job periodically, use the following GAQL " \ "query with GoogleAdsService.search:" puts query end end
پرل
sub check_job_status { my ($api_client, $customer_id, $offline_user_data_job_resource_name) = @_; my $search_query = "SELECT offline_user_data_job.resource_name, " . "offline_user_data_job.id, offline_user_data_job.status, " . "offline_user_data_job.type, offline_user_data_job.failure_reason, " . "offline_user_data_job.customer_match_user_list_metadata.user_list " . "FROM offline_user_data_job " . "WHERE offline_user_data_job.resource_name = " . "'$offline_user_data_job_resource_name' LIMIT 1"; my $search_request = Google::Ads::GoogleAds::V22::Services::GoogleAdsService::SearchGoogleAdsRequest ->new({ customerId => $customer_id, query => $search_query }); # Get the GoogleAdsService. my $google_ads_service = $api_client->GoogleAdsService(); my $iterator = Google::Ads::GoogleAds::Utils::SearchGoogleAdsIterator->new({ service => $google_ads_service, request => $search_request }); # The results have exactly one row. my $google_ads_row = $iterator->next; my $offline_user_data_job = $google_ads_row->{offlineUserDataJob}; my $status = $offline_user_data_job->{status}; printf "Offline user data job ID %d with type %s has status: %s.\n", $offline_user_data_job->{id}, $offline_user_data_job->{type}, $status; if ($status eq SUCCESS) { print_customer_match_user_list_info($api_client, $customer_id, $offline_user_data_job->{customerMatchUserListMetadata}{userList}); } elsif ($status eq FAILED) { print "Failure reason: $offline_user_data_job->{failureReason}"; } elsif (grep /$status/, (PENDING, RUNNING)) { print "To check the status of the job periodically, use the following GAQL " . "query with the GoogleAdsService->search() method:\n$search_query\n"; } return 1; }
برای تأیید اندازه لیست، میتوانید از منبع user_list
پرسوجو کنید.
مثال کد برای پرس و جو از منبع user_list
جاوا
try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { // Creates a query that retrieves the user list. String query = String.format( "SELECT user_list.size_for_display, user_list.size_for_search " + "FROM user_list " + "WHERE user_list.resource_name = '%s'", userListResourceName); // Constructs the SearchGoogleAdsStreamRequest. SearchGoogleAdsStreamRequest request = SearchGoogleAdsStreamRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .setQuery(query) .build(); // Issues the search stream request. ServerStream<SearchGoogleAdsStreamResponse> stream = googleAdsServiceClient.searchStreamCallable().call(request);
سی شارپ
// Get the GoogleAdsService. GoogleAdsServiceClient service = client.GetService(Services.V22.GoogleAdsService); // Creates a query that retrieves the user list. string query = "SELECT user_list.size_for_display, user_list.size_for_search " + "FROM user_list " + $"WHERE user_list.resource_name = '{userListResourceName}'"; // Issues a search stream request. service.SearchStream(customerId.ToString(), query, delegate (SearchGoogleAdsStreamResponse resp) { // Display the results. foreach (GoogleAdsRow userListRow in resp.Results) { UserList userList = userListRow.UserList; Console.WriteLine("The estimated number of users that the user list " + $"'{userList.ResourceName}' has is {userList.SizeForDisplay}" + $" for Display and {userList.SizeForSearch} for Search."); } } );
پی اچ پی
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); // Creates a query that retrieves the user list. $query = "SELECT user_list.size_for_display, user_list.size_for_search " . "FROM user_list " . "WHERE user_list.resource_name = '$userListResourceName'"; // Issues a search stream request. /** @var GoogleAdsServerStreamDecorator $stream */ $stream = $googleAdsServiceClient->searchStream( SearchGoogleAdsStreamRequest::build($customerId, $query) );
پایتون
googleads_service_client: GoogleAdsServiceClient = client.get_service( "GoogleAdsService" ) # Creates a query that retrieves the user list. query: str = f""" SELECT user_list.size_for_display, user_list.size_for_search FROM user_list WHERE user_list.resource_name = '{user_list_resource_name}'""" # Issues a search request. search_results: SearchGoogleAdsStreamResponse = ( googleads_service_client.search(customer_id=customer_id, query=query) )
روبی
query = <<~EOQUERY SELECT user_list.size_for_display, user_list.size_for_search FROM user_list WHERE user_list.resource_name = #{user_list} EOQUERY response = client.service.google_ads.search_stream( customer_id: customer_id, query: query, )
پرل
# Create a query that retrieves the user list. my $search_query = "SELECT user_list.size_for_display, user_list.size_for_search " . "FROM user_list " . "WHERE user_list.resource_name = '$user_list_resource_name'"; # Create a search Google Ads stream request that will retrieve the user list. my $search_stream_request = Google::Ads::GoogleAds::V22::Services::GoogleAdsService::SearchGoogleAdsStreamRequest ->new({ customerId => $customer_id, query => $search_query, }); # Get the GoogleAdsService. my $google_ads_service = $api_client->GoogleAdsService(); my $search_stream_handler = Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({ service => $google_ads_service, request => $search_stream_request });
برای اهداف حفظ حریم خصوصی، اندازه لیست کاربران تا زمانی که حداقل ۱۰۰ عضو داشته باشد، صفر نشان داده میشود. پس از آن، اندازه به دو رقم مهم گرد میشود.
خطاهایی که در طول اجرای OfflineUserDataJob
رخ میدهند را میتوان از طریق منبع offline_user_data_job
با استفاده از زبان جستجوی Google Ads دریافت کرد. با این حال، توجه داشته باشید که این گزارش حاوی اطلاعاتی در مورد هیچ تطابق ناموفقی نیست، زیرا فقط هشها هنگام انجام تطابقها مقایسه میشوند. اگر با لیست مشتریان خود با مشکلی مواجه شدید، به راهنمای عیبیابی مراجعه کنید.
با رابط کاربری گوگل ادز مقایسه کنید
ممکن است هنگام مشاهده در بخش مدیریت مخاطبان از رابط کاربری گوگل ادز، فهرستی کوچکتر از حد انتظار به نظر برسد. این نما تعداد کاربران فعال در فهرست را نشان میدهد. برای اطلاعات بیشتر، به این راهنمای عیبیابی مراجعه کنید.
از آنجایی که ممکن است تا ۲۴ ساعت طول بکشد تا یک لیست با اعضا پر شود، اگر بیشتر از هر ۱۲ ساعت یک بار در لیست مخاطبان خود پست بگذارید، ممکن است وضعیت In Progress
را در رابط کاربری گوگل ادز مشاهده کنید.
مرحله ۴: فهرست خود را هدف قرار دهید
شما میتوانید فهرست خود را در سطح گروه تبلیغاتی یا در سطح کمپین هدفگذاری کنید. این فرآیند مشابه سایر انواع معیارهای هدفگذاری در API است.
مثال کد برای هدف قرار دادن تبلیغات در گروه تبلیغاتی به لیست کاربران
جاوا
private String targetAdsInAdGroupToUserList( GoogleAdsClient googleAdsClient, long customerId, long adGroupId, String userList) { // Creates the ad group criterion targeting members of the user list. AdGroupCriterion adGroupCriterion = AdGroupCriterion.newBuilder() .setAdGroup(ResourceNames.adGroup(customerId, adGroupId)) .setUserList(UserListInfo.newBuilder().setUserList(userList).build()) .build(); // Creates the operation. AdGroupCriterionOperation operation = AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterion).build(); // Creates the ad group criterion service. try (AdGroupCriterionServiceClient adGroupCriterionServiceClient = googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) { // Adds the ad group criterion. MutateAdGroupCriteriaResponse response = adGroupCriterionServiceClient.mutateAdGroupCriteria( Long.toString(customerId), ImmutableList.of(operation)); // Gets and prints the results. String adGroupCriterionResourceName = response.getResults(0).getResourceName(); System.out.printf( "Successfully created ad group criterion with resource name '%s' " + "targeting user list with resource name '%s' with ad group with ID %d.%n", adGroupCriterionResourceName, userList, adGroupId); return adGroupCriterionResourceName; } }
سی شارپ
private string TargetAdsInAdGroupToUserList( GoogleAdsClient client, long customerId, long adGroupId, string userListResourceName) { // Get the AdGroupCriterionService client. AdGroupCriterionServiceClient adGroupCriterionServiceClient = client.GetService (Services.V22.AdGroupCriterionService); // Create the ad group criterion targeting members of the user list. AdGroupCriterion adGroupCriterion = new AdGroupCriterion { AdGroup = ResourceNames.AdGroup(customerId, adGroupId), UserList = new UserListInfo { UserList = userListResourceName } }; // Create the operation. AdGroupCriterionOperation adGroupCriterionOperation = new AdGroupCriterionOperation { Create = adGroupCriterion }; // Add the ad group criterion, then print and return the new criterion's resource name. MutateAdGroupCriteriaResponse mutateAdGroupCriteriaResponse = adGroupCriterionServiceClient.MutateAdGroupCriteria(customerId.ToString(), new[] { adGroupCriterionOperation }); string adGroupCriterionResourceName = mutateAdGroupCriteriaResponse.Results.First().ResourceName; Console.WriteLine("Successfully created ad group criterion with resource name " + $"'{adGroupCriterionResourceName}' targeting user list with resource name " + $"'{userListResourceName}' with ad group with ID {adGroupId}."); return adGroupCriterionResourceName; }
پی اچ پی
private static function targetAdsInAdGroupToUserList( GoogleAdsClient $googleAdsClient, int $customerId, int $adGroupId, string $userListResourceName ): string { // Creates the ad group criterion targeting members of the user list. $adGroupCriterion = new AdGroupCriterion([ 'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId), 'user_list' => new UserListInfo(['user_list' => $userListResourceName]) ]); // Creates the operation. $operation = new AdGroupCriterionOperation(); $operation->setCreate($adGroupCriterion); // Issues a mutate request to add an ad group criterion. $adGroupCriterionServiceClient = $googleAdsClient->getAdGroupCriterionServiceClient(); /** @var MutateAdGroupCriteriaResponse $adGroupCriterionResponse */ $adGroupCriterionResponse = $adGroupCriterionServiceClient->mutateAdGroupCriteria( MutateAdGroupCriteriaRequest::build($customerId, [$operation]) ); $adGroupCriterionResourceName = $adGroupCriterionResponse->getResults()[0]->getResourceName(); printf( "Successfully created ad group criterion with resource name '%s' " . "targeting user list with resource name '%s' with ad group with ID %d.%s", $adGroupCriterionResourceName, $userListResourceName, $adGroupId, PHP_EOL ); return $adGroupCriterionResourceName; }
پایتون
def target_ads_in_ad_group_to_user_list( client: GoogleAdsClient, customer_id: str, ad_group_id: str, user_list_resource_name: str, ) -> str: """Creates an ad group criterion that targets a user list with an ad group. Args: client: an initialized GoogleAdsClient instance. customer_id: a str client customer ID used to create an ad group criterion. ad_group_id: a str ID for an ad group used to create an ad group criterion that targets members of a user list. user_list_resource_name: a str resource name for a user list. Returns: a str resource name for an ad group criterion. """ ad_group_criterion_operation: AdGroupCriterionOperation = client.get_type( "AdGroupCriterionOperation" ) # Creates the ad group criterion targeting members of the user list. ad_group_criterion: AdGroupCriterion = ad_group_criterion_operation.create ad_group_criterion.ad_group = client.get_service( "AdGroupService" ).ad_group_path(customer_id, ad_group_id) ad_group_criterion.user_list.user_list = user_list_resource_name ad_group_criterion_service: AdGroupCriterionServiceClient = ( client.get_service("AdGroupCriterionService") ) response: MutateAdGroupCriteriaResponse = ( ad_group_criterion_service.mutate_ad_group_criteria( customer_id=customer_id, operations=[ad_group_criterion_operation] ) ) resource_name: str = response.results[0].resource_name print( "Successfully created ad group criterion with resource name: " f"'{resource_name}' targeting user list with resource name: " f"'{user_list_resource_name}' and with ad group with ID " f"{ad_group_id}." ) return resource_name
روبی
def target_ads_in_ad_group_to_user_list( client, customer_id, ad_group_id, user_list ) # Creates the ad group criterion targeting members of the user list. operation = client.operation.create_resource.ad_group_criterion do |agc| agc.ad_group = client.path.ad_group(customer_id, ad_group_id) agc.user_list = client.resource.user_list_info do |info| info.user_list = user_list end end # Issues a mutate request to create the ad group criterion. response = client.service.ad_group_criterion.mutate_ad_group_criteria( customer_id: customer_id, operations: [operation], ) ad_group_criterion_resource_name = response.results.first.resource_name puts "Successfully created ad group criterion with resource name " \ "'#{ad_group_criterion_resource_name}' targeting user list with resource name " \ "'#{user_list}' with ad group with ID #{ad_group_id}" ad_group_criterion_resource_name end
پرل
sub target_ads_in_ad_group_to_user_list { my ($api_client, $customer_id, $ad_group_id, $user_list_resource_name) = @_; # Create the ad group criterion targeting members of the user list. my $ad_group_criterion = Google::Ads::GoogleAds::V22::Resources::AdGroupCriterion->new({ adGroup => Google::Ads::GoogleAds::V22::Utils::ResourceNames::ad_group( $customer_id, $ad_group_id ), userList => Google::Ads::GoogleAds::V22::Common::UserListInfo->new({ userList => $user_list_resource_name })}); # Create the operation. my $ad_group_criterion_operation = Google::Ads::GoogleAds::V22::Services::AdGroupCriterionService::AdGroupCriterionOperation ->new({ create => $ad_group_criterion }); # Add the ad group criterion, then print and return the new criterion's resource name. my $ad_group_criteria_response = $api_client->AdGroupCriterionService()->mutate({ customerId => $customer_id, operations => [$ad_group_criterion_operation]}); my $ad_group_criterion_resource_name = $ad_group_criteria_response->{results}[0]{resourceName}; printf "Successfully created ad group criterion with resource name '%s' " . "targeting user list with resource name '%s' with ad group with ID %d.\n", $ad_group_criterion_resource_name, $user_list_resource_name, $ad_group_id; return $ad_group_criterion_resource_name; }
هدف قرار دادن چندین لیست مشتری
یک crm_based_user_list
فقط میتواند هنگام استفاده از logical_user_list
با crm_based_user_list
دیگری ترکیب شود. تمام سیاستهای crm_based_user_list
برای لیست کاربران حاصل اعمال میشود.