بدء استخدام "مطابقة العملاء"

تتيح لك ميزة "مطابقة العملاء" استخدام بياناتك على الإنترنت وبلا إنترنت للوصول إلى عملائك وإعادة جذبهم على "شبكة بحث Google" وفي علامة التبويب "التسوّق" وعلى Gmail وYouTube و"الشبكة الإعلانية". باستخدام المعلومات التي شاركها عملاؤك معك، تعمل "مطابقة العملاء" على توجيه الإعلانات إلى هؤلاء العملاء وغيرهم من العملاء المشابهين لهم. يمكنك تحميل بيانات إدارة العلاقات مع العملاء (CRM) بشكل مجمّع أو إلحاق البيانات أو إزالتها أو استخدام قوائم المستخدمين هذه لإنشاء logical_user_list.

اطّلِع على نظرة عامة على إدارة الجمهور للحصول على قائمة بأنواع شرائح الجمهور المختلفة لمقارنة ميزة "مطابقة العملاء" بخيارات قوائم المستخدمين الأخرى.

اطّلِع على مزيد من المعلومات عن مطابقة العميل واستهداف الجمهور.

المتطلبات الأساسية

ليست كل الحسابات مؤهَّلة لاستخدام ميزة "مطابقة العملاء". لاستخدام ميزة "مطابقة العملاء"، يجب أن يتضمّن حسابك ما يلي:

  • مستوى التزام عالٍ بالسياسات
  • سجلّ دفع جيد

تتوفر ميزات مختلفة وفقًا للمتطلبات التي يستوفيها حسابك. يُرجى الرجوع إلى سياسة "مطابقة العملاء" للاطّلاع على متطلبات أهلية استخدام هذه الميزة وقيودها.

تصميم عملية الدمج

يمكنك تصميم عملية الدمج.

مسار الاستخدام

في ما يلي الخطوات المقترَحة لإنشاء قائمة عملاء واستهدافها:

  1. أنشئ قائمة عملاء فارغة.

  2. أنشئ OfflineUserDataJob. من الناحية الكفاءة، من الأفضل إنشاء مهمة واحدة كبيرة بدلاً من عدة مهام صغيرة.

    تأكَّد من تعبئة حقل consent في customer_match_user_list_metadata في طلبات OfflineUserDataJob create. لا يلزم الحصول على موافقة في ما يتعلّق بطلبات remove. تعرض واجهة برمجة التطبيقات OfflineUserDataJobError.CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS إذا تم ضبط قيمة الوظيفة consent.ad_user_data أو consent.ad_personalization على DENIED.

    إذا رفض أحد المستخدمين الموافقة، يمكنك إنشاء وظيفة باستخدام عملية remove لإزالة معرّفات المستخدم من قائمة المستخدمين.

    إذا لم تحصل على الموافقة لمستخدمين محدّدين، يمكنك إنشاء مهمة منفصلة لا تتيح ضبط الحقل consent في customer_match_user_list_metadata الخاصة بالمهمة، ثم إضافة معرّفات لهؤلاء المستخدمين باستخدام عمليات create لتلك المهمة المنفصلة.

  3. أضِف عمليات باستخدام الوسيطة OfflineUserDataJobService.AddOfflineUserDataJobOperations . ننصحك بإضافة ما يصل إلى 10,000 معرّف في كلّ مكالمة لضمان المعالجة المثلى. يمكن أن يحتوي طلب AddOfflineUserDataJobOperations واحد على 100,000 معرّف كحد أقصى في جميع عناصر UserData في قائمة العمليات.

    على سبيل المثال، إذا كان كلّ عنصر من عناصر UserData يتضمّن UserIdentifier واحدًا لمحاولة hashed_email وUserIdentifier آخر لمحاولةhashed_phone_number، فإنّه يكون من الأفضل إرسال 5,000 عنصر UserData لكلّ طلب لأنّ كلّ طلب سيتضمّن 10,000 معرّف مستخدم في المجمل.

  4. كرِّر الخطوة السابقة إلى أن تتم إضافة جميع العمليات أو إلى أن تتم تعبئة المهمة بالسعة الكاملة. لا توجد حدود لعدد العمليات التي يمكنك إضافتها إلى المهمة الواحدة، ومع ذلك، نوصي بعدم أكثر من 1000000 عملية لكل مهمة من أجل المعالجة المثلى.

  5. شغِّل الوظيفة.

  6. استطلاع للتحقق من اكتمال عملية التحميل بنجاح

  7. تأكَّد من نسبة المطابقة.

  8. استهدف القائمة.

‫OfflineUserDataJobService وUserDataService

تتوفّر خدمتان لتحميل بيانات "مطابقة العملاء". اختَر الخدمة استنادًا إلى حالة استخدامك، إذ قد تكون هناك قيود مفروضة على إحدى الخدمات.

خدمات تحميل بيانات "مطابقة العملاء"
OfflineUserDataJobService (التنسيق المفضّل) يستخدم معظم المطوّرين هذه الخدمة. تم تحسينه لعمليات التحميل الكبيرة التي تتسم بمعدل نقل بيانات مرتفع، ويعرض مقاييس النجاح عند اكتمالها. يركّز هذا الدليل بشكل أساسي على هذه الخدمة.
UserDataService تم تحسين هذه الخدمة لتحميل عدد صغير من المعرّفات في المرة الواحدة مع إجراء تعديلات متقطعة، وهي ليست محسّنة للعمل بشكل مستمر. ويُسمح بحد أقصى 10 عمليات لكل طلب. بالإضافة إلى ذلك، لا يمكن أن يحتوي طلب واحد على أكثر من 100 عنصر في المجمل على مستوى كل user_identifiers.

للحصول على إرشادات حول عمليات التحميل باستخدام هذه الخدمة، يُرجى الانتقال إلى الدليل لإدارة عملية دمج ميزة "مطابقة العملاء".

بدءًا من الإصدار 15 من Google Ads API، عليك تعبئة الحقل consent ضمن customer_match_user_list_metadata في طلبات UploadUserDataRequest create. لا يلزم الحصول على موافقة في ما يتعلّق بطلبات remove. تعرض واجهة برمجة التطبيقات ردًا تم ضبط قيمة received_operations_count عليه على صفر للإشارة إلى عدم معالجة الطلب في حال ضبط consent.ad_user_data أو consent.ad_personalization على DENIED. إذا كان المعرّف لديه موافقة DENIED، يمكنك طلب إزالة المعرّف من قائمة المستخدِمين باستخدام عملية remove من UploadUserDataRequest.

أفضل الممارسات

ضَع أفضل الممارسات التالية في الاعتبار عند تصميم عملية دمج ميزة "مطابقة العملاء":

  • لا تحاول استخدام حسابات متعدّدة لتعديل قائمة مستخدمين واحدة. لا يمكن تعديل قائمة مستخدمين إلا من خلال حساب "إعلانات Google" أو حساب شريك data الذي أنشأها.

  • يجب زيادة عدد العمليات لكل AddOfflineUserDataJobOperationsRequest إلى 100,000 معرّف كحد أقصى لتجنّب أخطاء RESOURCE_EXHAUSTED .

  • لا تخلِط بين عمليتَي create وremove في OfflineUserDataJob نفسها. قد يؤدي ذلك إلى حدوث خطأ CONFLICTING_OPERATION.

  • يمكنك تفعيل partial_failure في AddOfflineUserDataJobOperationsRequest لاكتشاف أي عمليات تتضمّن مشاكل قبل تشغيل المهمة. يتم التحقّق من صحة العمليات عند تحميلها إلى OfflineUserDataJob.

  • تجنَّب تشغيل عدّة عمليات OfflineUserDataJob في الوقت نفسه تؤدي إلى تعديل قائمة المستخدمين نفسها (أي مهام متعددة تشير CustomerMatchUserListMetadata.user_list إلى اسم المورد نفسه). وقد يؤدي ذلك إلى حدوث خطأ CONCURRENT_MODIFICATION لأنّه لا يُسمح لوظائف متعددة بالعمل في القائمة نفسها في الوقت نفسه. يمكن أن يحدث هذا الخطأ أيضًا في حال محاولة تعديل قائمة في الوقت نفسه من خلال واجهة مستخدم "إعلانات Google" وGoogle Ads API. يُرجى العلم أنّ ذلك لا ينطبق على إضافة عمليات إلى مهمة PENDING، والتي يمكن تنفيذها في أي وقت قبل بدء المهمة.

  • إذا كانت لديك آلاف العمليات لتطبيقها، يمكنك إنشاء عملية OfflineUserDataJob تتضمّن جميع العمليات. لا تنشئ عدة مهام تتضمّن بضع مئات من العمليات فقط في كلّ منها ونفِّذها بشكل تسلسلي أو متزامن. إنّ المهمة الكبيرة الواحدة التي تتضمّن جميع عملياتك تكون فعالة بدرجة أكبر بكثير من المهام الصغيرة المتعددة، كما تقلّل من فرص مواجهة أخطاء في سير عملك.

للحصول على أفكار حول كيفية الاستفادة من قوائم العملاء لتحقيق أفضل استهداف، يُرجى الانتقال إلى مركز المساعدة.

إنشاء قائمة عملاء

أولاً، أنشئ قائمة عملاء باستخدام ملف csv الذي يتضمّن UserListService. يتم إنشاء قوائم العملاء من خلال ضبط الحقل crm_based_user_list في كائن user_list. يمكن ضبط الحقل crm_based_user_list على أنواع الحملات التي تتيح استهداف قوائم العملاء:

ميزة "مطابقة العملاء" في أنواع الحملات المختلفة
شبكة البحث تظهر الإعلانات على شبكة البحث.
الشبكة الإعلانية لا تظهر الإعلانات على الشبكة الإعلانية وعلى Gmail إلا إذا كانت هناك تصميمات إعلانات GSP .
ميزة "الانتشار على الشبكة الإعلانية" في "الحملات على شبكة البحث" لا تظهر الإعلانات على شبكة البحث وعلى Gmail إلا إذا كانت تتضمّن تصميمات إعلانات GSP .
حملات الفيديو لا تظهر الإعلانات على YouTube إلا إذا كانت هناك إعلانات 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 على 10,000 للإشارة إلى عدم انتهاء الصلاحية.

تحدِّد السمة membership_status ما إذا كانت القائمة تقبل مستخدمين جددًا.

مثال على رمز لإنشاء قائمة عملاء

Java

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")
          // Customer Match user lists can use a membership life span of 10,000 to indicate
          // unlimited; otherwise normal values apply.
          // 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.V18.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",
        // Customer Match user lists can use a membership life span of 10000 to
        // indicate unlimited; otherwise normal values apply.
        // 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',
        // Customer Match user lists can use a membership life span of 10000 to
        // indicate unlimited; otherwise normal values apply.
        // 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, customer_id):
    """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 = client.get_service("UserListService")

    # Creates the user list operation.
    user_list_operation = client.get_type("UserListOperation")

    # Creates the new user list.
    user_list = 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
    )
    # Customer Match user lists can set an unlimited membership life span;
    # to do so, use the special life span value 10000. Otherwise, membership
    # life span must be between 0 and 540 days inclusive. See:
    # https://developers.devsite.corp.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 = user_list_service_client.mutate_user_lists(
        customer_id=customer_id, operations=[user_list_operation]
    )
    user_list_resource_name = 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"
    # Customer Match user lists can use a membership life span of 10000 to
    # indicate unlimited; otherwise normal values apply.
    # 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::V18::Resources::UserList->new({
      name        => "Customer Match list #" . uniqid(),
      description =>
        "A list of customers that originated from email and physical addresses",
      # Customer Match user lists can use a membership life span of 10000 to
      # indicate unlimited; otherwise normal values apply.
      # 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::V18::Common::CrmBasedUserListInfo->new({
          uploadKeyType => CONTACT_INFO
        })});

  # Create the user list operation.
  my $user_list_operation =
    Google::Ads::GoogleAds::V18::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;
}
      

إضافة بيانات العملاء

مفاتيح المطابقة الأساسية الثلاثة هي عنوان البريد الإلكتروني والعنوان البريدي ورقم الهاتف. يمكنك استخدام رقم تعريف المستخدم ورقم تعريف الجهاز الجوّال كمفاتيح للمطابقة، إلا أنّ هذه الحلول أقل قابلية للمستقبل نظرًا لاعتمادها على ملفات تعريف الارتباط ورقم تعريف الجهاز. ننصحك بتحميل معلومات الاتصال الخاصة بالمستخدمين، مثل عنوان البريد الإلكتروني والعنوان البريدي ورقم الهاتف، كلما أمكن ذلك، بدلاً من أرقام تعريف قاعدة إدارة علاقات العملاء أو أرقام تعريف الأجهزة الجوّالة.

يمكن أن تحتوي كل قائمة مستخدمين على نوع واحد فقط من بيانات العملاء على النحو المحدّد في الحقل 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 قبل تحميلها. ولتوحيد نتائج التجزئة، تأكَّد من تنفيذ المهام التالية قبل تجزئة إحدى هذه القيم:

  • إزالة المسافات البيضاء البادئة واللاحقة
  • بالنسبة إلى الأسماء وعناوين البريد الإلكتروني والعناوين البريدية: حوِّل النص إلى أحرف لاتينية صغيرة.
  • بالنسبة إلى أرقام الهواتف: يجب تحويل كل رقم هاتف إلى التنسيق E164 قبل التجزئة. يمثل هذا التنسيق رقم هاتف كرقم يصل طوله إلى خمسة عشر رقمًا ويبدأ بعلامة +، على سبيل المثال، +12125650000 أو +442070313000. يمكن حذف العلامة + البادئة اختياريًا.

بالنسبة إلى عناوين البريد الإلكتروني، ليس عليك إزالة جميع النقاط (.) التي تسبق اسم النطاق في عناوين البريد الإلكتروني gmail.com وgooglemail.com لأنّه لا يزال يتم قبولها.

إذا لم يتم تنسيق معلومات الاتصال بشكل صحيح قبل التجزئة، سيظل واجهة برمجة التطبيقات تقبل المعلومات المجزّأة، ولكن لا يمكن مطابقتها مع عميل.

إذا أردت تحميل بيانات العنوان البريدي، يجب تضمين ما يلي على الأقل:

  • رمز البلد
  • رمز بريدي
  • الاسم الأول المجزّأ
  • اسم العائلة المجزّأ

في حال عدم توفّر أيّ من هذه الحقول، لا يمكن مطابقة العنوان.

على الرغم من أنّ قوائم العملاء يمكن أن تحتوي على upload_key_type واحد فقط، يمكن تحميل أنواع متعددة من معلومات الاتصال لupload_key_type من CONTACT_INFO. ويُنصح باستخدام هذا الإجراء لزيادة نِسب المطابقة.

تحميل أرقام تعريف عملاء إدارة علاقات العملاء

لتعبئة قائمة العملاء بأرقام تعريف إدارة علاقات العملاء، اضبط السمة 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 لإلحاق معلومات العميل الاتصال بقائمة عملاء.

Java

// 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());
}
      

#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 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
);
      

Python

def build_offline_user_data_job_operations(client):
    """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 = {
        "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 = {
        # 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 = {"email": "charlie@example.com"}

    # Adds the raw records to a raw input list.
    raw_records = [raw_record_1, raw_record_2, raw_record_3]

    operations = []
    # 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 = 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 = 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 = 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 = client.get_type("UserIdentifier")
                address_info = 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 = 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::V18::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::V18::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::V18::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::V18::Common::UserIdentifier->new({
              addressInfo =>
                Google::Ads::GoogleAds::V18::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::V18::Common::UserData->new({
          userIdentifiers => [$user_identifiers]});
      push(
        @$operations,
        Google::Ads::GoogleAds::V18::Services::OfflineUserDataJobService::OfflineUserDataJobOperation
          ->new({
            create => $user_data
          }));
    }
  }
      

التحقّق من تحميل القائمة ونسبة المطابقة

بعد أن يحصل OfflineUserDataJob على SUCCESS حالة، تصبح نسبة المطابقة المقدّرة متوفرة في الحقل operation_metadata.match_rate_range . إذا طلبت البحث في هذا الحقل قبل اكتمال المهمة، قد تكون القيمة في هذا الحقل صفرًا. لضمان أنّ نسبة المطابقة جاهزة لإثبات صحتها وأنّ القائمة جاهزة للاستهداف، ننصحك بالاستعلام عن المهمة لمعرفة ما إذا كانت قد اكتملت. قد يستغرق إكمال المهمة مدة تتراوح بين 10 دقائق و24 ساعة.

مثال على رمز للتحقق من حالة المهمة

Java

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.V18.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, customer_id, offline_user_data_job_resource_name):
    """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 = 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 = client.get_service("GoogleAdsService")
    results = google_ads_service.search(customer_id=customer_id, query=query)
    offline_user_data_job = next(iter(results)).offline_user_data_job
    status_name = offline_user_data_job.status.name
    user_list_resource_name = (
        offline_user_data_job.customer_match_user_list_metadata.user_list
    )

    print(
        f"Offline user data job ID '{offline_user_data_job.id}' with type "
        f"'{offline_user_data_job.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.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::V18::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->{failure_reason}";
  } 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

Java

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.V18.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 = client.get_service("GoogleAdsService")

# Creates a query that retrieves the user list.
query = 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 = 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::V18::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
  });
      

لأغراض الخصوصية، يظهر حجم قائمة المستخدمين على أنّه صفر إلى أن تتضمّن القائمة 1,000 عضو على الأقل. بعد ذلك، يتم تقريب الحجم إلى الرقمين الأكثر أهمية .

يمكن جلب الأخطاء أثناء تنفيذ OfflineUserDataJob من خلال المورد offline_user_data_job باستخدام لغة طلبات البحث في "إعلانات Google". يُرجى العِلم أنّ هذا التقرير لا يحتوي على معلومات عن أي مطابقات تعذّر إجراؤها لأنّه تتم مقارنة التجزئات فقط عند إجراء المطابقات. يمكنك الرجوع إلى دليل تحديد المشاكل وحلّها إذا واجهت مشاكل في قوائم العملاء.

المقارنة مع واجهة مستخدم "إعلانات Google"

قد تظهر القائمة أصغر مما تتوقّعه عند عرضها في "مدير الجمهور" من واجهة مستخدِم "إعلانات Google". تعرِض هذه الطريقة عدد المستخدِمين النشطين في القائمة. لمزيد من المعلومات، يُرجى الاطّلاع على دليل تحديد المشاكل وحلّها .

بما أنّه قد يستغرق ملء قائمة بالمشتركين مدة تصل إلى 24 ساعة، قد تظهر لك حالة In Progress في واجهة مستخدم "إعلانات Google" إذا كانت عملية التحميل تتم إلى قائمة جمهور بمعدّل أكثر من مرة واحدة كل 12 ساعة.

استهداف قائمتي

يمكنك استهداف قائمتك على مستوى المجموعة الإعلانية أو على مستوى الحملة. تشبه هذه العملية أنواعًا أخرى من معايير الاستهداف في واجهة برمجة التطبيقات.

مثال على الرمز لاستهداف الإعلانات في مجموعة إعلانية لقائمة مستخدمين

Java

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.V18.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, customer_id, ad_group_id, user_list_resource_name
):
    """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 = client.get_type("AdGroupCriterionOperation")
    # Creates the ad group criterion targeting members of the user list.
    ad_group_criterion = 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 = client.get_service("AdGroupCriterionService")
    response = ad_group_criterion_service.mutate_ad_group_criteria(
        customer_id=customer_id, operations=[ad_group_criterion_operation]
    )
    resource_name = 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::V18::Resources::AdGroupCriterion->new({
      adGroup => Google::Ads::GoogleAds::V18::Utils::ResourceNames::ad_group(
        $customer_id, $ad_group_id
      ),
      userList => Google::Ads::GoogleAds::V18::Common::UserListInfo->new({
          userList => $user_list_resource_name
        })});

  # Create the operation.
  my $ad_group_criterion_operation =
    Google::Ads::GoogleAds::V18::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 مع crm_based_user_list آخر إلا عند استخدام logical_user_list. تنطبق جميع سياسات crm_based_user_list على قائمة المستخدمين الناتجة.