شروع به کار با «مطابقت مشتری»

«مطابقت مشتری» به شما امکان می‌دهد از داده‌های آنلاین و آفلاین خود برای دسترسی و تعامل مجدد با مشتریانتان در «جستجو»، برگه Shopping،‏ Gmail،‏ YouTube، و «شبکه تبلیغات» استفاده کنید. بااستفاده از اطلاعاتی که مشتریانتان با شما هم‌رسانی کرده‌اند، «مطابقت مشتری» آگهی‌ها را برای آن مشتریان و مشتریان دیگری مثل آن‌ها هدف‌یابی می‌کند. می‌توانید داده‌های مدیریت ارتباط با مشتری (CRM) را به‌صورت انبوه بارگذاری کنید، داده‌ها را پیوست یا حذف کنید، یا از این فهرست‌های کاربر برای ایجاد logical_user_list استفاده کنید.

برای مقایسه «مطابقت مشتری» با دیگر گزینه‌های فهرست کاربر، نمای کلی مدیریت مخاطب را برای فهرستی از انواع مختلف بخش مخاطب ببینید.

درباره مطابقت مشتری و هدف‌یابی مخاطب بیشتر بدانید.

پیش‌نیازها

همه حساب‌ها برای استفاده از «مطابقت مشتری» واجدشرایط نیستند. برای استفاده از «مطابقت مشتری»، حساب شما باید موارد زیر را داشته باشد:

  • سابقه خوب از رعایت خط‌مشی
  • سابقه پرداخت خوب

بسته به اینکه حسابتان کدام الزامات را برآورده می‌کند، ویژگی‌های مختلفی دردسترس است. برای اطلاع از الزامات واجدشرایط بودن و محدودیت‌ها، به خط‌مشی «مطابقت مشتری» مراجعه کنید.

قبل‌از شروع: پیاده‌سازی‌تان را برنامه‌ریزی کنید

قبل‌از شروع نوشتن هر کدی، مهم است که پیاده‌سازی «مطابقت مشتری» خود را برنامه‌ریزی کنید. این بخش فرایند کلی و ملاحظات کلیدی را شرح می‌دهد تا به شما کمک کند ادغامی قوی طراحی کنید. وقتی طرح واضحی داشتید، می‌توانید مراحل پیاده‌سازی را که در ادامه آمده است دنبال کنید.

جریان استفاده

جریان توصیه‌شده برای ایجاد و هدف‌یابی فهرست مشتریان در اینجا آمده است:

  1. فهرست مشتری خالی ایجاد کنید.

  2. OfflineUserDataJob ایجاد کنید. ایجاد یک کار بزرگ واحد بسیار کارآمدتر از ایجاد چند کار کوچک‌تر است.

    مطمئن شوید که فیلد consent customer_match_user_list_metadata را در درخواست‌های OfflineUserDataJob create خود پر کنید. برای درخواست‌های remove، رضایت لازم نیست. اگر consent.ad_user_data یا consent.ad_personalization شغل روی DENIED تنظیم شده باشد، API مقدار OfflineUserDataJobError.CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS را برمی‌گرداند.

    اگر کاربری رضایت نداده باشد، می‌توانید کاری با عملیات remove ایجاد کنید تا شناسه‌های کاربر را از فهرست کاربر بردارید.

    اگر برای کاربران خاصی موافقت ندارید، کار جداگانه‌ای ایجاد کنید که در آن فیلد consent کار customer_match_user_list_metadata را تنظیم نکنید، سپس بااستفاده از عملیات create برای آن کار جداگانه، شناسه‌های آن کاربران را اضافه کنید.

  3. بااستفاده از روش OfflineUserDataJobService.AddOfflineUserDataJobOperations عملیات اضافه کنید. توصیه می‌کنیم برای پردازش بهینه، حداکثر ۱۰٬۰۰۰ شناسه را در یک فراخوانی اضافه کنید. یک درخواست AddOfflineUserDataJobOperations می‌تواند حداکثر ۱۰۰٬۰۰۰ شناسه در همه اشیاء UserData در فهرست عملیات داشته باشد.

    برای مثال، اگر هریک از اشیای UserData شما یک UserIdentifier برای hashed_email و یک UserIdentifier دیگر برای hashed_phone_number داشته باشد، ارسال ۵٬۰۰۰ شیء UserData در هر درخواست بهینه است زیرا هر درخواست درمجموع حاوی ۱۰٬۰۰۰ شناسه کاربر است.

  4. مرحله قبلی را تکرار کنید تا همه عملیات‌ها اضافه شوند یا تا زمانی که کار به ظرفیت برسد. محدودیتی برای تعداد عملیاتی که می‌توانید به یک کار اضافه کنید وجود ندارد؛ بااین‌حال، برای پردازش بهینه، توصیه می‌کنیم بیش‌از ۱٬۰۰۰٬۰۰۰ عملیات در هر کار نداشته باشید.

  5. اجرای کار. باید کار را ظرف ۵ روز پس‌از ایجاد آن اجرا کنید. درغیراین‌صورت، کار دیگر برای اجرا دردسترس نخواهد بود.

  6. نظرسنجی برای بارگذاری موفق.

  7. نرخ مطابقت را درستی‌سنجی کنید.

  8. فهرست را هدف‌یابی کنید.

OfflineUserDataJobService و UserDataService

دو سرویس برای بارگذاری داده‌های «مطابقت مشتری» دردسترس است. سرویس را براساس مورد استفاده‌تان انتخاب کنید چون ممکن است برای سرویس محدودیت‌هایی وجود داشته باشد.

خدمات بارگذاری «تطابق مشتری»
OfflineUserDataJobService (برگزیده) اکثر توسعه‌دهندگان از این سرویس استفاده می‌کنند. این روش برای بارگذاری‌های بزرگ با توان گذرداد بالا بهینه‌سازی شده است و پس‌از تکمیل، سنجه‌های موفقیت را برمی‌گرداند. این راهنما در اصل روی این سرویس تمرکز می‌کند.
UserDataService این سرویس برای بارگذاری تعداد کمی شناسه در هر بار با به‌روزرسانی‌های پراکنده بهینه‌سازی شده است و برای اجرای مداوم بهینه‌سازی نشده است. این روش محدودیت ۱۰ عملیات در هر درخواست دارد. علاوه‌براین، یک درخواست واحد نمی‌تواند در مجموع بیش‌از ۱۰۰ مورد در همه user_identifiers داشته باشد.

برای راهنمایی درباره بارگذاری با این سرویس، به راهنما برای مدیریت یکپارچه‌سازی «تطابق مشتری» مراجعه کنید.

باید فیلد consent customer_match_user_list_metadata را در درخواست‌های UploadUserDataRequest create خود پر کنید. برای remove درخواست، رضایت لازم نیست. اگر consent.ad_user_data یا consent.ad_personalization برابر با DENIED باشد، میانای برنامه‌سازی کاربردی پاسخی با received_operations_count تنظیم‌شده روی صفر برمی‌گرداند که نشان می‌دهد درخواست پردازش نشده است. اگر شناسه‌ای دارای رضایت DENIED باشد، می‌توانید درخواست کنید شناسه از فهرست کاربر بااستفاده از عملیات remove UploadUserDataRequest برداشته شود.

روال‌های مطلوب

هنگام طراحی ادغام «مطابقت مشتری»، روال‌های مطلوب زیر را درنظر داشته باشید:

  • از چند حساب برای اصلاح یک فهرست کاربران استفاده نکنید. فقط حساب Google Ads یا شریک داده که فهرست کاربر را ایجاد کرده است می‌تواند آن را اصلاح کند.

  • تعداد عملیات در هر AddOfflineUserDataJobOperationsRequest را تا حداکثر ۱۰۰٬۰۰۰ شناسه افزایش دهید تا از خطاهای RESOURCE_EXHAUSTED جلوگیری کنید.

  • عملیات create و remove را در یک OfflineUserDataJob ترکیب نکنید. انجام این کار می‌تواند منجر به خطای CONFLICTING_OPERATION شود.

  • partial_failure را در AddOfflineUserDataJobOperationsRequest فعال کنید تا عملکرد مشکل‌ساز را قبل‌از اجرای کار تشخیص دهید. عملیات‌ها هنگام بارگذاری در OfflineUserDataJob اعتبارسنجی می‌شوند.

  • برای جلوگیری از خطاهای CONCURRENT_MODIFICATION هنگام به‌روزرسانی فهرست‌های کاربر:

    از داشتن چندین فرایند OfflineUserDataJob در وضعیت RUNNING به‌طور هم‌زمان خودداری کنید، اگر آن‌ها همان نام منبع فهرست کاربران را هدف قرار می‌دهند، که در CustomerMatchUserListMetadata.user_list مشخص شده است. این خطا به این دلیل رخ می‌دهد که چندین کار به‌طور هم‌زمان تلاش می‌کنند فهرست یکسانی را اصلاح کنند. این تداخل همچنین می‌تواند زمانی رخ دهد که شما فهرست را ازطریق رابط کاربری Google Ads درحین پردازش یک کار API تغییر دهید.

    این محدودیت برای کارهایی که شروع شده‌اند، یعنی در وضعیت RUNNING هستند، اعمال می‌شود. درمقابل، می‌توانید با اطمینان چندین درخواست AddOfflineUserDataJobOperations برای افزودن داده به یک OfflineUserDataJob ارسال کنید درحالی‌که هنوز در وضعیت PENDING است. عملیات را می‌توان در هرزمانی قبل‌از فراخوانی RunOfflineUserDataJob برای شروع فرایند به کار اضافه کرد.

  • اگر هزاران عملیات برای اعمال دارید، یک OfflineUserDataJob حاوی همه عملیات‌ها ایجاد کنید. چندین کار با فقط چند صد عملیات برای هرکدام ایجاد نکنید و آن‌ها را به‌صورت متوالی یا هم‌زمان اجرا نکنید. یک کار بزرگ با همه عملیات‌های شما بسیار کارآمدتر از چندین کار کوچک است و احتمال مواجه شدن با خطا در گردش کار را کاهش می‌دهد.

برای ایده‌هایی درباره نحوه استفاده از فهرست‌های مشتری برای هدف‌یابی بهینه، به روال‌های مطلوب «تطابق مشتری» مراجعه کنید.

مرحله ۱: ایجاد فهرست مشتری

فهرست مشتری را با UserListService ایجاد کنید. فهرست‌های مشتری با تنظیم فیلد crm_based_user_list در user_list ساخته می‌شود. فیلد crm_based_user_list را می‌توان در انواع پویشی که از هدف‌یابی فهرست‌های مشتریان پشتیبانی می‌کنند تنظیم کرد:

«مطابقت مشتری» در انواع مختلف پویش
شبکه جستجو آگهی‌ها در شبکه «جستجوی Google» نشان داده می‌شود.
شبکه تبلیغات آگهی‌ها در «شبکه تبلیغات Google» نشان داده می‌شود.
«گسترش در شبکه تبلیغات» در پویش‌های «جستجو» آگهی‌ها در شبکه «جستجوی Google» و «شبکه تبلیغات Google» نشان داده می‌شوند.
کمپین‌های «تولید تقاضا» آگهی‌ها در YouTube، «یافته‌ها»، و Gmail نشان داده می‌شوند (بااستفاده از منبع Audience در AdGroupCriterion.audience هدف‌یابی می‌شوند).
پویش‌های «عملکرد بیشینه» آگهی‌ها در همه کانال‌های Google نشان داده می‌شود (به‌عنوان نشان مخاطب در AssetGroupSignal.audience استفاده می‌شود).
کمپین‌های ویدیویی آگهی‌ها در YouTube نشان داده می‌شوند.
کمپین‌های خرید آگهی‌ها در برگه Shopping نشان داده می‌شود.

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.V26.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
      

پرل

sub create_customer_match_user_list {
  my ($api_client, $customer_id) = @_;

  # Create the user list.
  my $user_list = Google::Ads::GoogleAds::V26::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::V26::Common::CrmBasedUserListInfo->new({
          uploadKeyType => CONTACT_INFO
        })});

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

مرحله ۲: افزودن اعضا به فهرست کاربر

سه کلید مطابقت اصلی عبارتند از نشانی ایمیل، نشانی پستی، و شماره تلفن. می‌توانید از شناسه کاربر و شناسه دستگاه همراه به‌عنوان کلیدهای مطابقت استفاده کنید، اما این راه‌حل‌ها با توجه به اتکایشان به کوکی‌ها و شناسه دستگاه، کمتر برای آینده مناسب هستند. توصیه می‌کنیم درصورت امکان، اطلاعات تماس کاربر (مانند نشانی ایمیل، نشانی پستی، و شماره تلفن) را به‌جای شناسه تلفن همراه یا CRM بارگذاری کنید.

هر فهرست کاربر فقط می‌تواند حاوی یک نوع داده مشتری باشد که توسط فیلد CrmBasedUserListInfo.upload_key_type مشخص شده است. علاوه‌براین، یک شیء UserData که نشان‌دهنده یک کاربر است، می‌تواند تا ۲۰ شناسه کاربر داشته باشد که هرکدام شیء UserIdentifier خود را دارند. بیش‌از ۲۰ شناسه منجر به خطای TOO_MANY_USER_IDENTIFIERS می‌شود.

Google Ads فقط درصورتی از فهرست کاربر «مطابقت مشتری» برای هدف‌یابی استفاده می‌کند که حداقل آستانه کاربران فعال را در زمان ارائه آگهی برآورده کرده باشد؛ کاربران فعال تعداد کاربران موجود در فهرست شما است که در Gmail، «جستجو»، YouTube، یا «شبکه تبلیغاتی» فعال هستند. حداقل ۵٬۰۰۰ عضو بارگذاری کنید تا احتمال داشتن کاربران فعال مطابقت‌یافته کافی برای هدف‌یابی افزایش یابد.

بارگذاری اطلاعات تماس کاربر

برای بارگذاری نشانی ایمیل، نشانی پستی، یا شماره تلفن کاربر، upload_key_type را روی CONTACT_INFO تنظیم کنید. اطلاعات تماس باید با «حساب Google» مرتبط باشد تا مطابقت داده شود، و حساب‌های شرکتی (مثل Google Workspace) را نمی‌توان هدف‌یابی کرد.

به‌دلیل نگرانی‌های مربوط به حریم خصوصی، نشانی‌های ایمیل، نام‌های کوچک، نام‌های خانوادگی، و شماره تلفن‌ها باید قبل‌از بارگذاری بااستفاده از الگوریتم SHA-256 درهم‌سازی شوند. برای استانداردسازی نتایج درهم‌سازی، قبل‌از درهم‌سازی یکی از این مقادیر، مطمئن شوید که وظایف زیر را انجام داده‌اید:

اگر اطلاعات تماس قبل‌از درهم‌سازی به‌درستی قالب‌بندی نشده باشد، میانای برنامه‌سازی کاربردی همچنان اطلاعات درهم‌شده را می‌پذیرد، اما نمی‌توان آن را با مشتری مطابقت داد.

اگر می‌خواهید داده‌های نشانی پستی را بارگذاری کنید، باید حداقل موارد زیر را اضافه کنید:

  • کد کشور
  • کد پستی
  • نام درهم‌شده
  • نام خانوادگی درهم‌سازی‌شده

اگر هریک از این فیلدها وجود نداشته باشد، نشانی نمی‌تواند مطابقت داده شود.

اگرچه فهرست‌های مشتریان فقط می‌توانند یک upload_key_type داشته باشند، چندین نوع اطلاعات تماس را می‌توان برای upload_key_type CONTACT_INFO بارگذاری کرد. این گزینه برای افزایش نرخ مطابقت توصیه می‌شود.

قالب‌بندی نشانی ایمیل برای تبدیل‌های بهبودیافته

برای اطمینان از بالاترین نرخ مطابقت برای تبدیل‌های به‌سازی‌شده، باید نشانی‌های ایمیل را بااستفاده از مراحل زیر به‌درستی قالب‌بندی و درهم‌سازی کنید:

  1. اعمال کردن عادی‌سازی استاندارد (همه نشانی‌های ایمیل):

    • هرگونه فاصله سفید ASCII در ابتدا و انتهای متن را حذف کنید.
    • همه نویسه‌های نشانی ایمیل را به حروف کوچک تبدیل کنید.
  2. اعمال نرمال‌سازی مختص دامنه (فقط 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 نرمال‌سازی می‌شود.
  3. نشانی ایمیل نرمال‌سازی‌شده را درهم‌سازی کنید:

    • رشته ایمیل نرمال‌شده را به‌صورت بایت‌های UTF-8 کدبندی کنید.
    • بایت‌های UTF-8 را بااستفاده از الگوریتم SHA-256 درهم‌سازی کنید.
    • خلاصه حاصل را به‌عنوان رشته شانزده‌شانزدهی با حروف کوچک (۶۴ نویسه) قالب‌بندی کنید.
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()

بارگذاری شناسه‌های CRM

برای پر کردن فهرست مشتری با شناسه‌های CRM،‏ upload_key_type را روی CRM_ID تنظیم کنید. شناسه‌های CRM از شناسه کاربری تولیدشده و اختصاص‌یافته توسط تبلیغ‌کننده مطابقت داده می‌شوند. این کار شبیه بارگذاری 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 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: 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
      

پرل

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

curl

مرحله ۳: درستی‌سنجی کردن بارگذاری فهرست و نرخ مطابقت

وقتی OfflineUserDataJob SUCCESS وضعیت داشته باشد، نرخ تطابق تخمینی در فیلد operation_metadata.match_rate_range دردسترس است. اگر پیش‌از تکمیل کار این فیلد را پُر کنید، مقدار این فیلد ممکن است صفر باشد. برای اطمینان از اینکه نرخ مطابقت شما برای درستی‌سنجی آماده است و فهرست برای هدف‌یابی آماده است، توصیه می‌کنیم کار را برای تکمیل نظرسنجی کنید. تکمیل این کار می‌تواند از ۱۰ دقیقه تا ۲۴ ساعت طول بکشد.

نمونه کد برای بررسی وضعیت کار

جاوا

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.V26.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
      

پرل

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::V26::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.V26.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,
)
      

پرل

# 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::V26::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

برای حفظ حریم خصوصی، اندازه فهرست کاربر تا زمانی که فهرست حداقل ۱۰۰ عضو نداشته باشد، صفر نشان داده می‌شود. پس‌از آن، اندازه به دو رقم باارزش‌تر گرد می‌شود.

خطاهای حین اجرای OfflineUserDataJob را می‌توان ازطریق منبع offline_user_data_job بااستفاده از «زبان پُرسمان Google Ads» واکشی کرد. بااین‌حال، این گزارش حاوی اطلاعاتی درباره مطابقت‌های ناموفق نیست، زیرا هنگام انجام مطابقت‌ها فقط درهم‌سازی‌ها مقایسه می‌شوند. اگر با فهرست‌های مشتری‌تان مشکل دارید، به راهنمای عیب‌یابی مراجعه کنید.

مقایسه با «میانای کاربری Google Ads»

وقتی فهرست در «مدیر مخاطبان» از «میانای کاربری Google Ads» مشاهده می‌شود، ممکن است کوچک‌تر از حد انتظار به‌نظر برسد. این نما تعداد کاربران فعال را در فهرست نشان می‌دهد. برای اطلاعات بیشتر، این راهنمای عیب‌یابی را ببینید.

ازآنجایی‌که ممکن است تا ۲۴ ساعت طول بکشد تا یک فهرست با اعضا پر شود، اگر بیش‌از یک بار در هر ۱۲ ساعت در فهرست مخاطبان بارگذاری کنید، ممکن است In Progress وضعیت را در واسط کاربری Google Ads ببینید.

مرحله ۴: هدف‌یابی فهرست

می‌توانید فهرستتان را در سطح گروه آگهی یا در سطح پویش هدف‌یابی کنید. این فرایند مشابه انواع دیگر معیارهای هدف‌یابی در API است.

نمونه کد برای هدف‌یابی آگهی‌ها در گروه آگهی به فهرست کاربر

جاوا

private String targetAdsInAdGroupToUserList(
    GoogleAdsClient googleAdsClient, long customerId, long adGroupId, String userList) {
  // Creates the ad group criterion targeting members of the user list.
  AdGroupCriterion adGroupCriterion =
      AdGroupCriterion.newBuilder()
          .setAdGroup(ResourceNames.adGroup(customerId, adGroupId))
          .setUserList(UserListInfo.newBuilder().setUserList(userList).build())
          .build();

  // Creates the operation.
  AdGroupCriterionOperation operation =
      AdGroupCriterionOperation.newBuilder().setCreate(adGroupCriterion).build();

  // Creates the ad group criterion service.
  try (AdGroupCriterionServiceClient adGroupCriterionServiceClient =
      googleAdsClient.getLatestVersion().createAdGroupCriterionServiceClient()) {
    // Adds the ad group criterion.
    MutateAdGroupCriteriaResponse response =
        adGroupCriterionServiceClient.mutateAdGroupCriteria(
            Long.toString(customerId), ImmutableList.of(operation));
    // Gets and prints the results.
    String adGroupCriterionResourceName = response.getResults(0).getResourceName();
    System.out.printf(
        "Successfully created ad group criterion with resource name '%s' "
            + "targeting user list with resource name '%s' with ad group with ID %d.%n",
        adGroupCriterionResourceName, userList, adGroupId);
    return adGroupCriterionResourceName;
  }
}

      

C#‎

private string TargetAdsInAdGroupToUserList(
    GoogleAdsClient client, long customerId, long adGroupId, string userListResourceName)
{
    // Get the AdGroupCriterionService client.
    AdGroupCriterionServiceClient adGroupCriterionServiceClient = client.GetService
        (Services.V26.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
      

پرل

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::V26::Resources::AdGroupCriterion->new({
      adGroup => Google::Ads::GoogleAds::V26::Utils::ResourceNames::ad_group(
        $customer_id, $ad_group_id
      ),
      userList => Google::Ads::GoogleAds::V26::Common::UserListInfo->new({
          userList => $user_list_resource_name
        })});

  # Create the operation.
  my $ad_group_criterion_operation =
    Google::Ads::GoogleAds::V26::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 به شما امکان می‌دهد فهرست‌های موجودتان را با افزودن یا برداشتن اعضا مدیریت کنید.

عملیات کلیدی برای به‌روزرسانی فهرست‌هایتان شامل موارد زیر است:

  • کاربران جدید را اضافه کنید: داده‌های مشتری جدید را به فهرست موجود اضافه کنید.
  • برداشتن کاربران خاص: کاربران را به‌صورت تکی براساس شناسه‌هایشان از فهرست بردارید.
  • جایگزین کردن همه اعضا: فهرست موجود را پاک کنید و محتوای آن را کاملاً جایگزین کنید، هرچند توصیه می‌شود به‌جای این کار، اعضا را اضافه و حذف کنید.

مدیریت فهرست‌های مشتری را ببینید.