تتيح لك ميزة "مطابقة العملاء" استخدام بياناتك على الإنترنت وبلا إنترنت للوصول إلى عملائك وإعادة جذبهم على "شبكة بحث Google" وفي علامة التبويب "التسوّق" وعلى Gmail وYouTube و"شبكة Google الإعلانية". باستخدام المعلومات التي شاركها عملاؤك معك، تعمل أداة "مطابقة العملاء" على توجيه الإعلانات إلى هؤلاء العملاء وغيرهم من العملاء المشابهين لهم. يمكنك تحميل بيانات إدارة العلاقات مع العملاء (CRM) بشكل مجمّع أو إلحاق البيانات أو إزالتها أو استخدام قوائم المستخدمين هذه لإنشاء logical_user_list.
يمكنك الاطّلاع على نظرة عامة على إدارة الجمهور للحصول على قائمة بأنواع شرائح الجمهور المختلفة لمقارنة "مطابقة العملاء" بخيارات قوائم المستخدمين الأخرى.
مزيد من المعلومات عن "مطابقة العملاء" واستهداف الجمهور
المتطلبات الأساسية
لا تكون بعض الحسابات مؤهَّلة لاستخدام ميزة "مطابقة العملاء". لاستخدام "مطابقة العملاء"، يجب أن يتوفّر في حسابك ما يلي:
- سجلّ جيد من الالتزام بالسياسات
- سجلّ جيد من الدفع
تتوفّر ميزات مختلفة حسب المتطلبات التي يستوفيها حسابك. يُرجى الرجوع إلى سياسة "مطابقة العملاء" للاطّلاع على متطلبات الأهلية والقيود.
قبل البدء: التخطيط لعملية التنفيذ
قبل البدء في كتابة أي رمز، من المهم التخطيط لتنفيذ "مطابقة العملاء". يوضّح هذا القسم العملية الشاملة والاعتبارات الرئيسية لمساعدتك في تصميم عملية دمج قوية. بعد وضع خطة واضحة، يمكنك المتابعة وتنفيذ الخطوات التالية.
مسار الاستخدام
في ما يلي المسار المقترَح لإنشاء قائمة عملاء واستهدافها:
أنشئ قائمة عملاء فارغة.
أنشئ
OfflineUserDataJob. من الأفضل إنشاء مهمة كبيرة واحدة بدلاً من عدة مهام أصغر.تأكَّد من ملء حقل
consentفيcustomer_match_user_list_metadataفي طلباتOfflineUserDataJobcreate. بالنسبة إلى طلباتremove، لا يلزم الحصول على موافقة. تعرض واجهة برمجة التطبيقات القيمةOfflineUserDataJobError.CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMSإذا تم ضبطconsent.ad_user_dataأوconsent.ad_personalizationفي الوظيفة علىDENIED.إذا رفض المستخدم تقديم موافقته، يمكنك إنشاء مهمة تتضمّن عملية
removeلإزالة معرّفات المستخدم من قائمة المستخدمين.إذا لم تكن لديك موافقة من مستخدمين معيّنين، أنشِئ مهمة منفصلة لا تضبط فيها الحقل
consentفيcustomer_match_user_list_metadataالخاص بالمهمة، ثم أضِف معرّفات لهؤلاء المستخدمين باستخدام عملياتcreateلتلك المهمة المنفصلة.أضِف عمليات باستخدام طريقة
OfflineUserDataJobService.AddOfflineUserDataJobOperations. ننصح بإضافة ما يصل إلى 10,000 معرّف إجمالاً في طلب واحد لضمان المعالجة المثلى. يمكن أن يحتوي طلبAddOfflineUserDataJobOperationsواحد على 100,000 معرّف كحد أقصى في جميع عناصرUserDataفي قائمة العمليات.على سبيل المثال، إذا كان كل عنصر من عناصر
UserDataيحتوي علىUserIdentifierواحد لـhashed_emailوUserIdentifierآخر لـhashed_phone_number، يكون إرسال 5,000 عنصرUserDataلكل طلب هو الخيار الأمثل لأنّ كل طلب يحتوي على 10,000 معرّف مستخدم إجمالاً.كرِّر الخطوة السابقة إلى أن تتم إضافة جميع العمليات أو إلى أن تصل مهمة الاستيراد إلى الحد الأقصى. ما مِن حدود لعدد العمليات التي يمكنك إضافتها إلى مهمة واحدة، ولكننا ننصح بعدم تجاوز 1,000,000 عملية لكل مهمة لضمان المعالجة المثلى.
نفِّذ المهمة. يجب تنفيذ المهمة في غضون 5 أيام من إنشائها. وإلا، لن تكون المهمة متاحة للتشغيل.
استطلاع للتحميل الناجح.
تحقَّق من نسبة المطابقة.
استهدِف القائمة.
OfflineUserDataJobService وUserDataService
تتوفّر خدمتان لتحميل بيانات "مطابقة العملاء". اختَر الخدمة استنادًا إلى حالة الاستخدام، إذ قد تكون هناك قيود على الخدمة.
| خدمات تحميل بيانات "مطابقة العملاء" | |
|---|---|
OfflineUserDataJobService
(مفضَّل)
|
يستخدم معظم المطوّرين هذه الخدمة. تم تحسين هذه الطريقة لعمليات التحميل الكبيرة مع معدل نقل بيانات مرتفع، كما تعرض مقاييس النجاح عند اكتمال العملية. يركّز هذا الدليل بشكل أساسي على هذه الخدمة. |
UserDataService
|
تم تحسين هذه الخدمة لتحميل عدد صغير من المعرّفات في المرة الواحدة
مع تحديثات متفرقة، ولم يتم تحسينها للتشغيل بشكل مستمر. يبلغ الحد الأقصى لعدد العمليات المسموح بها 10 عمليات لكل طلب. بالإضافة إلى ذلك، لا يمكن أن يحتوي طلب واحد على أكثر من 100 عنصر في المجموع في جميع
user_identifiers.
للحصول على إرشادات بشأن عمليات التحميل باستخدام هذه الخدمة، يُرجى الانتقال إلى الدليل الخاص بإدارة عملية دمج "مطابقة العملاء". يجب ملء الحقل
|
أفضل الممارسات
يُرجى مراعاة أفضل الممارسات التالية عند تصميم عملية دمج ميزة "مطابقة العملاء":
لا تحاول استخدام حسابات متعددة لتعديل قائمة مستخدمين واحدة. لا يمكن تعديل قائمة المستخدمين إلا من خلال حساب "إعلانات Google" أو حساب شريك البيانات الذي أنشأها.
يمكنك زيادة عدد العمليات لكل
AddOfflineUserDataJobOperationsRequestإلى 100,000 معرّف لتجنُّب أخطاءRESOURCE_EXHAUSTED.لا تخلط بين عمليات
createوremoveضمنOfflineUserDataJobنفسه. قد يؤدي ذلك إلى ظهور الخطأCONFLICTING_OPERATION.فعِّل
partial_failureفيAddOfflineUserDataJobOperationsRequestلرصد أي عمليات بها مشاكل قبل تشغيل المهمة. يتم التحقّق من صحة العمليات عند تحميلها إلىOfflineUserDataJob.لمنع حدوث أخطاء
CONCURRENT_MODIFICATIONعند تعديل قوائم المستخدمين:تجنَّب تنفيذ عمليات
OfflineUserDataJobمتعددة في حالةRUNNINGفي الوقت نفسه إذا كانت تستهدف اسم مورد قائمة المستخدمين نفسه المحدّد فيCustomerMatchUserListMetadata.user_list. يحدث الخطأ لأنّ هناك وظائف متعددة تحاول تعديل القائمة نفسها في الوقت نفسه. يمكن أن يحدث هذا التعارض أيضًا إذا عدّلت القائمة من خلال واجهة مستخدم "إعلانات Google" أثناء معالجة مهمة في واجهة برمجة التطبيقات.ينطبق هذا القيد على الوظائف التي تم بدءها، أي التي تكون في حالة
RUNNING. في المقابل، يمكنك بأمان إرسال طلباتAddOfflineUserDataJobOperationsمتعددة لإضافة بيانات إلىOfflineUserDataJobواحد عندما يكون في الحالةPENDING. يمكن إضافة العمليات إلى مهمة في أي وقت قبل استدعاءRunOfflineUserDataJobلبدء العملية.إذا كان لديك آلاف العمليات التي تريد تطبيقها، أنشئ
OfflineUserDataJobواحدًا يحتوي على جميع العمليات. لا تنشئ عدة مهام تحتوي كل منها على بضع مئات من العمليات فقط وتنفّذها بشكل تسلسلي أو متزامن. إنّ تنفيذ مهمة واحدة كبيرة تتضمّن جميع العمليات أكثر كفاءة بكثير من تنفيذ عدة مهام صغيرة، ويقلّل من احتمال حدوث أخطاء في سير العمل.
للحصول على أفكار حول كيفية استخدام قوائم العملاء لتحقيق الاستهداف الأمثل، يُرجى الاطّلاع على أفضل الممارسات المتعلّقة بميزة "مطابقة العملاء".
الخطوة 1: إنشاء قائمة عملاء
أنشئ قائمة عملاء باستخدام UserListService. يتم إنشاء قوائم العملاء من خلال ضبط الحقل crm_based_user_list في العنصر user_list. يمكن ضبط الحقل crm_based_user_list على أنواع الحملات التي تتيح استهداف قوائم العملاء:
| "مطابقة العملاء" في أنواع الحملات المختلفة | |
|---|---|
| شبكة البحث | تظهر الإعلانات على "شبكة بحث Google". |
| الشبكة الإعلانية | تظهر الإعلانات على "شبكة Google الإعلانية". |
| ميزة "الانتشار على الشبكة الإعلانية" في "الحملات على شبكة البحث" | تظهر الإعلانات على "شبكة بحث Google" و"شبكة Google الإعلانية". |
| الحملات لزيادة الطلب |
تظهر الإعلانات على YouTube و"اقتراحات" وGmail (يتم استهدافها باستخدام مورد Audience في AdGroupCriterion.audience).
|
| حملات الأداء الأفضل |
تظهر الإعلانات على جميع قنوات Google (تُستخدَم كإشارة لشرائح الجمهور على
AssetGroupSignal.audience).
|
| حملات الفيديو | تظهر الإعلانات على YouTube. |
| حملات التسوّق | تظهر الإعلانات في علامة التبويب "التسوّق". |
يحتوي crm_based_user_list على ثلاثة حقول:
app_id: سلسلة تحدّد بشكل فريد التطبيق على الأجهزة الجوّالة الذي تم جمع البيانات منه. هذا الإجراء مطلوب عند إنشاءCrmBasedUserListلتحميل معرِّفات إعلانية على الأجهزة الجوّالة.
upload_key_type: نوع مفتاح مطابق للقائمة، ويمكن أن يكونCONTACT_INFOأوCRM_IDأوMOBILE_ADVERTISING_ID. لا يُسمح بأنواع البيانات المختلطة في القائمة نفسها. هذا الحقل مطلوب لجميع قوائم العملاء.data_source_type: مصدر بيانات القائمة القيمة التلقائية هيFIRST_PARTY. يمكن للعملاء المدرَجين في القائمة المسموح بها إنشاء قوائم عملاء من مصادر خارجية (THIRD_PARTY_CREDIT_BUREAUأوTHIRD_PARTY_VOTER_FILEأوTHIRD_PARTY_PARTNER_DATA). يمكن دمج القوائم من مصدرFIRST_PARTYفقط مع قوائم أخرى.
تتيح لك السمة membership_life_span لقائمة المستخدمين تحديد الفترة الزمنية، بالأيام، التي يُعتبر فيها المستخدم مدرجًا في القائمة. يجب ألا تزيد قيمة membership_life_span لقائمة مستخدمين في "مطابقة العملاء" عن 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(); } }
#C
private string CreateCustomerMatchUserList(GoogleAdsClient client, long customerId) { // Get the UserListService. UserListServiceClient service = client.GetService(Services.V25.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; }
PHP
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; }
Python
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
Ruby
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
Perl
sub create_customer_match_user_list { my ($api_client, $customer_id) = @_; # Create the user list. my $user_list = Google::Ads::GoogleAds::V25::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::V25::Common::CrmBasedUserListInfo->new({ uploadKeyType => CONTACT_INFO })}); # Create the user list operation. my $user_list_operation = Google::Ads::GoogleAds::V25::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; }
curl
الخطوة 2: إضافة أعضاء إلى قائمة المستخدمين
مفاتيح المطابقة الأساسية الثلاثة هي عنوان البريد الإلكتروني والعنوان البريدي ورقم الهاتف. يمكنك استخدام معرّف المستخدِم ومعرّف الجهاز الجوّال كمفاتيح مطابقة، ولكنّ هذه الحلول أقل ملاءمة للمستقبل لأنّها تعتمد على ملفات تعريف الارتباط ومعرّف الجهاز. ننصحك بتحميل معلومات الاتصال بالمستخدم، مثل عنوان البريد الإلكتروني والعنوان البريدي ورقم الهاتف، إن أمكن، بدلاً من أرقام تعريف إدارة علاقات العملاء أو الأجهزة الجوّالة.
يمكن أن تحتوي كل قائمة مستخدمين على نوع واحد فقط من بيانات العملاء على النحو المحدّد في الحقل CrmBasedUserListInfo.upload_key_type. بالإضافة إلى ذلك، يمكن أن يحتوي العنصر
UserData، الذي يمثّل مستخدمًا واحدًا، على ما يصل إلى 20 معرّفًا للمستخدمين، ولكلّ معرّف عنصر UserIdentifier خاص به. سيؤدي استخدام أكثر من 20 معرّفًا إلى ظهور الخطأ TOO_MANY_USER_IDENTIFIERS.
لا تستخدم "إعلانات Google" قائمة مستخدمين في "مطابقة العملاء" للاستهداف إلا إذا استوفت الحدّ الأدنى من المستخدمين النشطين في وقت عرض الإعلان. والمستخدمون النشطون هم عدد المستخدمين في قائمتك الذين ينشطون على Gmail أو "بحث Google" أو YouTube أو "الشبكة الإعلانية". حمِّل 5,000 عضو على الأقل لزيادة فرص توفّر عدد كافٍ من المستخدمين النشطين المطابقين لاستهدافهم.
تحميل معلومات الاتصال الخاصة بالمستخدم
لتحميل عناوين البريد الإلكتروني للمستخدمين أو العناوين البريدية أو أرقام الهواتف، اضبط
upload_key_type على CONTACT_INFO. يجب أن تكون معلومات الاتصال مرتبطة بحساب على Google لتتم مطابقتها، ولا يمكن استهداف حسابات الشركات، مثل Google Workspace.
للحيلولة دون أي مخاوف متعلقة بالخصوصية، يجب تجزئة عناوين البريد الإلكتروني والأسماء الأولى وأسماء العائلة وأرقام الهواتف باستخدام خوارزمية SHA-256 قبل تحميلها. لتوحيد نتائج التجزئة، عليك إجراء ما يلي قبل تجزئة إحدى هذه القيم:
- إزالة المسافات البيضاء البادئة واللاحقة
- تحويل النص إلى أحرف لاتينية صغيرة
- تنسيق أرقام الهواتف وفقًا لمعيار E.164
- بالنسبة إلى عناوين البريد الإلكتروني، اتّبِع التعليمات الواردة في مقالة تنسيق عناوين البريد الإلكتروني للإحالات الناجحة المحسّنة.
إذا لم يتم تنسيق معلومات الاتصال بشكلٍ سليم قبل التجزئة، سيظل بإمكان واجهة برمجة التطبيقات قبول المعلومات المجزّأة، ولكن لن يكون من الممكن مطابقتها مع أحد العملاء.
إذا أردت تحميل بيانات العناوين البريدية، يجب تضمين ما يلي على الأقل:
- رمز البلد
- الرمز البريدي
- الاسم الأول المجزّأ
- اسم العائلة المجزّأ
في حال عدم توفّر أيّ من هذه الحقول، لا يمكن مطابقة العنوان.
على الرغم من أنّ قوائم العملاء يمكن أن تحتوي على upload_key_type واحد فقط، يمكن تحميل أنواع متعددة من معلومات الاتصال لـ upload_key_type من CONTACT_INFO.
يُنصح باستخدام هذا الخيار لزيادة معدّلات المطابقة.
تنسيق عنوان البريد الإلكتروني لميزة "الإحالات الناجحة المحسّنة"
لضمان أعلى نسب مطابقة للإحالات الناجحة المحسّنة، عليك تنسيق عناوين البريد الإلكتروني وتجزئتها بشكل صحيح باتّباع الخطوات التالية:
تطبيق التسوية العادية (جميع عناوين البريد الإلكتروني):
- إزالة أي مسافة بيضاء بادئة ولاحقة في ASCII
- تحويل جميع الأحرف في عنوان البريد الإلكتروني إلى أحرف صغيرة
تطبيق التسوية الخاصة بالنطاق (
gmail.comوgooglemail.comفقط):- بعد تحويل عنوان البريد الإلكتروني إلى أحرف صغيرة، تحقَّق مما إذا كان النطاق (بعد الرمز
@) هوgmail.comأوgooglemail.com. - إزالة النقاط (
.): من جزء اسم المستخدم (قبل الرمز@)، أزِل جميع أحرف النقاط. - إزالة اللاحقات التي تتضمّن علامة الجمع (
+): من جزء اسم المستخدم، تتم إزالة علامة الجمع الأولى (+) وجميع الأحرف اللاحقة حتى الرمز@.- مثال: يتم أولاً تحويل
Jane.Doe+Shopping@googlemail.comإلىjane.doe+shopping@googlemail.com(أحرف صغيرة)، ثم إلىjanedoe@googlemail.com(قواعد Gmail وGooglemail).
- مثال: يتم أولاً تحويل
- النطاقات الأخرى: بالنسبة إلى أي نطاق غير
gmail.comأوgooglemail.com، لا تزِل النقاط أو اللاحقات التي تتضمّن علامة الجمع من اسم المستخدم. يتم تطبيق التسوية العادية فقط (إزالة المسافات البيضاء وتحويل الأحرف إلى أحرف صغيرة).- يتم تحويل المثال:
user.name+NYC@Example.comإلىuser.name+nyc@example.com.
- يتم تحويل المثال:
- بعد تحويل عنوان البريد الإلكتروني إلى أحرف صغيرة، تحقَّق مما إذا كان النطاق (بعد الرمز
تجزئة عنوان البريد الإلكتروني العادي:
- ترميز سلسلة عنوان البريد الإلكتروني الذي تمّت تسويته على أنّه بايت UTF-8
- جزِّئ وحدات بايت UTF-8 باستخدام خوارزمية SHA-256.
- يجب تنسيق الملخّص الناتج كسلسلة سداسية عشرية بأحرف صغيرة (64 حرفًا).
import hashlib
import re
def normalize_and_hash_email(email: str) -> str:
"""Normalizes and SHA-256 hashes an email address for enhanced conversions."""
normalized = email.strip().lower()
parts = normalized.split("@")
if len(parts) != 2:
raise ValueError("Invalid email address format.")
username, domain = parts
if domain in ("gmail.com", "googlemail.com"):
username = username.replace(".", "")
username = re.sub(r"\+.*$", "", username)
normalized = f"{username}@{domain}"
return hashlib.sha256(normalized.encode("utf-8")).hexdigest()
تحميل أرقام تعريف إدارة علاقات العملاء
لتعبئة قائمة العملاء بمعرّفات إدارة علاقات العملاء، اضبط upload_key_type على
CRM_ID. تتم مطابقة أرقام تعريف إدارة علاقات العملاء من رقم تعريف مستخدم أنشأه المعلِن وخصّصه. يشبه ذلك تحميل مثيلات MOBILE_ADVERTISING_ID، ولكن
بدلاً من ذلك، يمكنك ملء حقل third_party_user_id في عنصر UserIdentifier.
تحميل بيانات التعريف الرقمية
على غرار ميزة "مطابقة العملاء" باستخدام عناوين البريد الإلكتروني، يمكنك إجراء مطابقة العملاء باستخدام معرّفات الأجهزة الجوّالة، مثل معرّف المعلِنين (IDFA) أو معرّف الإعلانات من Google (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, dashes, and parentheses that will be removed later. .put("phone", "+1 (800) 555-0101") .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 (.) and plus (+) suffix before the Gmail domain. .put("email", "alex.2+myalias@gmail.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-555-0102") .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(normalizeAndHashEmailAddress(sha256Digest, rawRecord.get("email"))) .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( normalizeAndHashPhoneNumber(sha256Digest, rawRecord.get("phone"))) .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()); }
#C
// 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 }); }
PHP
// 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, dashes, and parentheses that will be removed later. 'phone' => '+1 (800) 555-0101' ]; $rawRecords[] = $rawRecord1; // The second user data has an email address, a mailing address, and a phone number. $rawRecord2 = [ // Email address that includes a period (.) and plus (+) suffix before the Gmail domain. 'email' => 'alex.2+myalias@gmail.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-555-0102', ]; $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::normalizeAndHashEmailAddress($rawRecord['email']) ] ); // 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::normalizeAndHashPhoneNumber($rawRecord['phone']) ] ); // Adds the hashed phone number 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 );
Python
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)
Ruby
# 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
Perl
# 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::V25::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::V25::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::V25::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::V25::Common::UserIdentifier->new({ addressInfo => Google::Ads::GoogleAds::V25::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::V25::Common::UserData->new({ userIdentifiers => [$user_identifiers]}); push( @$operations, Google::Ads::GoogleAds::V25::Services::OfflineUserDataJobService::OfflineUserDataJobOperation ->new({ create => $user_data })); } }
curl
الخطوة 3: التحقّق من تحميل القائمة ونسبة المطابقة
عندما تصبح OfflineUserDataJob بحالة SUCCESS، تتوفّر نسبة المطابقة المقدَّرة في حقل operation_metadata.match_rate_range. إذا
أرسلت طلب بحث عن هذا الحقل قبل اكتمال المهمة، قد تكون القيمة في هذا الحقل
صفرًا. لضمان أنّ نسبة المطابقة جاهزة للتحقّق وأنّ القائمة جاهزة للاستهداف، ننصحك بإجراء استطلاع حول اكتمال المهمة. قد يستغرق إكمال المهمة مدة تتراوح بين 10 دقائق و24 ساعة.
مثال على الرمز البرمجي للتحقّق من حالة المهمة
جافا
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); } } }
#C
private static void CheckJobStatusAndPrintResults(GoogleAdsClient client, long customerId, string offlineUserDataJobResourceName) { // Get the GoogleAdsService. GoogleAdsServiceClient service = client.GetService(Services.V25.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; } }
PHP
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 ); } }
Python
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}" )
Ruby
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
Perl
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::V25::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; }
curl
للتحقّق من حجم القائمة، يمكنك الاستعلام عن المورد 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);
#C
// Get the GoogleAdsService. GoogleAdsServiceClient service = client.GetService(Services.V25.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."); } } );
PHP
$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) );
Python
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) )
Ruby
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, )
Perl
# 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::V25::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 });
curl
لأغراض متعلّقة بالخصوصية، يظهر حجم قائمة المستخدمين على أنّه صفر إلى أن تتضمّن القائمة 100 مستخدم على الأقل. بعد ذلك، يتم تقريب الحجم إلى الرقمين الأكثر أهمية.
يمكن جلب الأخطاء التي تحدث أثناء تنفيذ OfflineUserDataJob من خلال مورد offline_user_data_job باستخدام لغة طلب البحث في "إعلانات Google". ومع ذلك، لا يحتوي هذا التقرير على معلومات حول أي تطابقات فاشلة، لأنّه تتم مقارنة التجزئات فقط عند إجراء التطابقات. راجِع دليل تحديد المشاكل وحلّها إذا واجهت مشاكل في قوائم العملاء.
المقارنة مع واجهة مستخدم "إعلانات Google"
قد تظهر القائمة أصغر من المتوقع عند عرضها في "مدير الجمهور" من واجهة مستخدم "إعلانات Google". تعرِض طريقة العرض هذه عدد المستخدِمين النشطين في القائمة. لمزيد من المعلومات، اطّلِع على دليل تحديد المشاكل وحلّها.
بما أنّ تعبئة القائمة بالمشتركين قد تستغرق مدة تصل إلى 24 ساعة، قد تظهر لك الحالة In Progress في واجهة مستخدم "إعلانات Google" إذا حمّلت بيانات إلى قائمة مستخدمين بوتيرة أكبر من مرّة واحدة كل 12 ساعة.
الخطوة 4: استهداف قائمتك
يمكنك استهداف قائمتك على مستوى المجموعة الإعلانية أو على مستوى الحملة. وتشبه هذه العملية الأنواع الأخرى من معايير الاستهداف في واجهة برمجة التطبيقات.
مثال على رمز برمجي لاستهداف الإعلانات في مجموعة إعلانية لقائمة مستخدمين
جافا
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; } }
#C
private string TargetAdsInAdGroupToUserList( GoogleAdsClient client, long customerId, long adGroupId, string userListResourceName) { // Get the AdGroupCriterionService client. AdGroupCriterionServiceClient adGroupCriterionServiceClient = client.GetService (Services.V25.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; }
PHP
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; }
Python
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
Ruby
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
Perl
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::V25::Resources::AdGroupCriterion->new({ adGroup => Google::Ads::GoogleAds::V25::Utils::ResourceNames::ad_group( $customer_id, $ad_group_id ), userList => Google::Ads::GoogleAds::V25::Common::UserListInfo->new({ userList => $user_list_resource_name })}); # Create the operation. my $ad_group_criterion_operation = Google::Ads::GoogleAds::V25::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; }
curl
استهداف عدّة قوائم عملاء
لا يمكن دمج crm_based_user_list إلا مع crm_based_user_list آخر
عند استخدام logical_user_list. تنطبق جميع سياسات
crm_based_user_list على قائمة المستخدمين الناتجة.
إدارة قوائمك وتعديلها
بعد إنشاء قوائم العملاء، من المحتمل أن تحتاج إلى تعديلها بشكل دوري لتعكس التغييرات في قاعدة عملائك. تتيح لك Google Ads API إدارة قوائمك الحالية من خلال إضافة أعضاء أو إزالتهم.
تشمل العمليات الرئيسية لتعديل قوائمك ما يلي:
- إلحاق مستخدمين جدد: أضِف بيانات عملاء جديدة إلى قائمة حالية.
- إزالة مستخدمين محدّدين: يمكنك إزالة مستخدمين فرديين من قائمة استنادًا إلى معرّفاتهم.
- استبدال جميع الأعضاء: يمكنك محو قائمة حالية واستبدال محتواها بالكامل، مع أنّه من الأفضل إضافة أعضاء وإزالتهم بدلاً من ذلك.
يُرجى الاطّلاع على المقالة إدارة قوائم العملاء.