ניהול רשימות של לקוחות

במדריך הזה מוסבר איך לעדכן רשימות לקוחות, להסיר לקוחות מהרשימות ולדווח על נתונים.

עדכון רשימה באמצעות OfflineUserDataJobService

אחרי שיוצרים את רשימות הלקוחות ומגדירים את הטירגוט, מומלץ לרענן אותן באופן קבוע.

כדי לעדכן את הרשימות עם הנתונים העדכניים, בדרך כלל יעיל יותר להוסיף או להסיר משתמשים ספציפיים, במקום להסיר את כל המשתמשים מהרשימה ולהעלות אותם מחדש.

הוספה לרשימה

כדי להוסיף נתונים לרשימה קיימת, יוצרים OfflineUserDataJob באותו אופן שבו יוצרים רשימת לקוחות חדשה.

Java

private void addUsersToCustomerMatchUserList(
    GoogleAdsClient googleAdsClient,
    long customerId,
    boolean runJob,
    String userListResourceName,
    Long offlineUserDataJobId,
    ConsentStatus adPersonalizationConsent,
    ConsentStatus adUserDataConsent)
    throws UnsupportedEncodingException {
  try (OfflineUserDataJobServiceClient offlineUserDataJobServiceClient =
      googleAdsClient.getLatestVersion().createOfflineUserDataJobServiceClient()) {
    String offlineUserDataJobResourceName;
    if (offlineUserDataJobId == null) {
      // Creates a new offline user data job.
      OfflineUserDataJob.Builder offlineUserDataJobBuilder =
          OfflineUserDataJob.newBuilder()
              .setType(OfflineUserDataJobType.CUSTOMER_MATCH_USER_LIST)
              .setCustomerMatchUserListMetadata(
                  CustomerMatchUserListMetadata.newBuilder().setUserList(userListResourceName));
      // Adds consent information to the job if specified.
      if (adPersonalizationConsent != null || adUserDataConsent != null) {
        Consent.Builder consentBuilder = Consent.newBuilder();
        if (adPersonalizationConsent != null) {
          consentBuilder.setAdPersonalization(adPersonalizationConsent);
        }
        if (adUserDataConsent != null) {
          consentBuilder.setAdUserData(adUserDataConsent);
        }
        // Specifies whether user consent was obtained for the data you are uploading. See
        // https://www.google.com/about/company/user-consent-policy for details.
        offlineUserDataJobBuilder
            .getCustomerMatchUserListMetadataBuilder()
            .setConsent(consentBuilder);
      }

      // Issues a request to create the offline user data job.
      CreateOfflineUserDataJobResponse createOfflineUserDataJobResponse =
          offlineUserDataJobServiceClient.createOfflineUserDataJob(
              Long.toString(customerId), offlineUserDataJobBuilder.build());
      offlineUserDataJobResourceName = createOfflineUserDataJobResponse.getResourceName();
      System.out.printf(
          "Created an offline user data job with resource name: %s.%n",
          offlineUserDataJobResourceName);
    } else {
      // Reuses the specified offline user data job.
      offlineUserDataJobResourceName =
          ResourceNames.offlineUserDataJob(customerId, offlineUserDataJobId);
    }

    // Issues a request to add the operations to the offline user data job. This example
    // only adds a few operations, so it only sends one AddOfflineUserDataJobOperations request.
    // If your application is adding a large number of operations, split the operations into
    // batches and send multiple AddOfflineUserDataJobOperations requests for the SAME job. See
    // https://developers.google.com/google-ads/api/docs/remarketing/audience-types/customer-match#customer_match_considerations
    // and https://developers.google.com/google-ads/api/docs/best-practices/quotas#user_data
    // for more information on the per-request limits.
    List<OfflineUserDataJobOperation> userDataJobOperations = buildOfflineUserDataJobOperations();
    AddOfflineUserDataJobOperationsResponse response =
        offlineUserDataJobServiceClient.addOfflineUserDataJobOperations(
            AddOfflineUserDataJobOperationsRequest.newBuilder()
                .setResourceName(offlineUserDataJobResourceName)
                .setEnablePartialFailure(true)
                .addAllOperations(userDataJobOperations)
                .build());

    // Prints the status message if any partial failure error is returned.
    // NOTE: The details of each partial failure error are not printed here, you can refer to
    // the example HandlePartialFailure.java to learn more.
    if (response.hasPartialFailureError()) {
      GoogleAdsFailure googleAdsFailure =
          ErrorUtils.getInstance().getGoogleAdsFailure(response.getPartialFailureError());
      System.out.printf(
          "Encountered %d partial failure errors while adding %d operations to the offline user "
              + "data job: '%s'. Only the successfully added operations will be executed when "
              + "the job runs.%n",
          googleAdsFailure.getErrorsCount(),
          userDataJobOperations.size(),
          response.getPartialFailureError().getMessage());
    } else {
      System.out.printf(
          "Successfully added %d operations to the offline user data job.%n",
          userDataJobOperations.size());
    }

    if (!runJob) {
      System.out.printf(
          "Not running offline user data job '%s', as requested.%n",
          offlineUserDataJobResourceName);
      return;
    }

    // Issues an asynchronous request to run the offline user data job for executing
    // all added operations.
    offlineUserDataJobServiceClient.runOfflineUserDataJobAsync(offlineUserDataJobResourceName);

    // BEWARE! The above call returns an OperationFuture. The execution of that future depends on
    // the thread pool which is owned by offlineUserDataJobServiceClient. If you use this future,
    // you *must* keep the service client in scope too.
    // See https://developers.google.com/google-ads/api/docs/client-libs/java/lro for more detail.

    // Offline user data jobs may take 6 hours or more to complete, so instead of waiting for the
    // job to complete, retrieves and displays the job status once. If the job is completed
    // successfully, prints information about the user list. Otherwise, prints the query to use
    // to check the job again later.
    checkJobStatus(googleAdsClient, customerId, offlineUserDataJobResourceName);
  }
}

      

C#‎

private static string AddUsersToCustomerMatchUserList(GoogleAdsClient client,
    long customerId, string userListResourceName, bool runJob,
    long? offlineUserDataJobId, ConsentStatus? adPersonalizationConsent,
    ConsentStatus? adUserDataConsent)
{
    // Get the OfflineUserDataJobService.
    OfflineUserDataJobServiceClient service = client.GetService(
        Services.V25.OfflineUserDataJobService);

    string offlineUserDataJobResourceName;
    if (offlineUserDataJobId == null)
    {
        // Creates a new offline user data job.
        OfflineUserDataJob offlineUserDataJob = new OfflineUserDataJob()
        {
            Type = OfflineUserDataJobType.CustomerMatchUserList,
            CustomerMatchUserListMetadata = new CustomerMatchUserListMetadata()
            {
                UserList = userListResourceName,
            }
        };

        if (adUserDataConsent != null || adPersonalizationConsent != null)
        {
            // Specifies whether user consent was obtained for the data you are uploading.
            // See https://www.google.com/about/company/user-consent-policy
            // for details.
            offlineUserDataJob.CustomerMatchUserListMetadata.Consent = new Consent();

            if (adPersonalizationConsent != null)
            {
                offlineUserDataJob.CustomerMatchUserListMetadata.Consent.AdPersonalization =
                    (ConsentStatus)adPersonalizationConsent;
            }

            if (adUserDataConsent != null)
            {
                offlineUserDataJob.CustomerMatchUserListMetadata.Consent.AdUserData =
                    (ConsentStatus)adUserDataConsent;
            }
        }

        // Issues a request to create the offline user data job.
        CreateOfflineUserDataJobResponse response1 = service.CreateOfflineUserDataJob(
            customerId.ToString(), offlineUserDataJob);
        offlineUserDataJobResourceName = response1.ResourceName;
        Console.WriteLine($"Created an offline user data job with resource name: " +
            $"'{offlineUserDataJobResourceName}'.");
    } else {
        // Reuses the specified offline user data job.
        offlineUserDataJobResourceName =
            ResourceNames.OfflineUserDataJob(customerId, offlineUserDataJobId.Value);
    }

    AddOfflineUserDataJobOperationsRequest request =
        new AddOfflineUserDataJobOperationsRequest()
        {
            ResourceName = offlineUserDataJobResourceName,
            Operations = { BuildOfflineUserDataJobOperations() },
            EnablePartialFailure = true,
        };
    // Issues a request to add the operations to the offline user data job. This example
    // only adds a few operations, so it only sends one AddOfflineUserDataJobOperations
    // request.
    // If your application is adding a large number of operations, split the operations into
    // batches and send multiple AddOfflineUserDataJobOperations requests for the SAME job.
    // See https://developers.google.com/google-ads/api/docs/remarketing/audience-types/customer-match#customer_match_considerations
    // and https://developers.google.com/google-ads/api/docs/best-practices/quotas#user_data
    // for more information on the per-request limits.
    AddOfflineUserDataJobOperationsResponse response2 =
        service.AddOfflineUserDataJobOperations(request);

    // Prints the status message if any partial failure error is returned.
    // Note: The details of each partial failure error are not printed here,
    // you can refer to the example HandlePartialFailure.cs to learn more.
    if (response2.PartialFailureError != null)
    {
        // Extracts the partial failure from the response status.
        GoogleAdsFailure partialFailure = response2.PartialFailure;
        Console.WriteLine($"{partialFailure.Errors.Count} partial failure error(s) " +
            $"occurred");
    }
    Console.WriteLine("The operations are added to the offline user data job.");

    if (!runJob)
    {
        Console.WriteLine($"Not running offline user data job " +
            "'{offlineUserDataJobResourceName}', as requested.");
        return offlineUserDataJobResourceName;
    }

    // Issues an asynchronous request to run the offline user data job for executing
    // all added operations.
    Operation<Empty, OfflineUserDataJobMetadata> operationResponse =
        service.RunOfflineUserDataJob(offlineUserDataJobResourceName);

    Console.WriteLine("Asynchronous request to execute the added operations started.");

    // Since offline user data jobs may take 24 hours or more to complete, it may not be
    // practical to do operationResponse.PollUntilCompleted() to wait for the results.
    // Instead, we save the offlineUserDataJobResourceName and use GoogleAdsService.Search
    // to check for the job status periodically.
    // In case you wish to follow the PollUntilCompleted or PollOnce approach, make sure
    // you keep both operationResponse and service variables alive until the polling
    // completes.

    return offlineUserDataJobResourceName;
}
      

PHP

    private static function addUsersToCustomerMatchUserList(
        GoogleAdsClient $googleAdsClient,
        int $customerId,
        bool $runJob,
        ?string $userListResourceName,
        ?int $offlineUserDataJobId,
        ?int $adPersonalizationConsent,
        ?int $adUserDataConsent
    ) {
        $offlineUserDataJobServiceClient =
            $googleAdsClient->getOfflineUserDataJobServiceClient();

        if (is_null($offlineUserDataJobId)) {
            // Creates a new offline user data job.
            $offlineUserDataJob = new OfflineUserDataJob(
                [
                'type' => OfflineUserDataJobType::CUSTOMER_MATCH_USER_LIST,
                'customer_match_user_list_metadata' => new CustomerMatchUserListMetadata(
                    [
                    'user_list' => $userListResourceName
                    ]
                )
                ]
            );
            // Adds consent information to the job if specified.
            if (!empty($adPersonalizationConsent) || !empty($adUserDataConsent)) {
                $consent = new Consent();
                if (!empty($adPersonalizationConsent)) {
                    $consent->setAdPersonalization($adPersonalizationConsent);
                }
                if (!empty($adUserDataConsent)) {
                    $consent->setAdUserData($adUserDataConsent);
                }
                // Specifies whether user consent was obtained for the data you are uploading. See
                // https://www.google.com/about/company/user-consent-policy for details.
                $offlineUserDataJob->getCustomerMatchUserListMetadata()->setConsent($consent);
            }

            // Issues a request to create the offline user data job.
            /**
 * @var CreateOfflineUserDataJobResponse $createOfflineUserDataJobResponse
*/
            $createOfflineUserDataJobResponse =
                $offlineUserDataJobServiceClient->createOfflineUserDataJob(
                    CreateOfflineUserDataJobRequest::build($customerId, $offlineUserDataJob)
                );
            $offlineUserDataJobResourceName = $createOfflineUserDataJobResponse->getResourceName();
            printf(
                "Created an offline user data job with resource name: '%s'.%s",
                $offlineUserDataJobResourceName,
                PHP_EOL
            );
        } else {
            // Reuses the specified offline user data job.
            $offlineUserDataJobResourceName =
                ResourceNames::forOfflineUserDataJob($customerId, $offlineUserDataJobId);
        }

        // Issues a request to add the operations to the offline user data job. This example
        // only adds a few operations, so it only sends one AddOfflineUserDataJobOperations request.
        // If your application is adding a large number of operations, split the operations into
        // batches and send multiple AddOfflineUserDataJobOperations requests for the SAME job. See
        // https://developers.google.com/google-ads/api/docs/remarketing/audience-types/customer-match#customer_match_considerations
        // and https://developers.google.com/google-ads/api/docs/best-practices/quotas#user_data
        // for more information on the per-request limits.
        /**
 * @var AddOfflineUserDataJobOperationsResponse $operationResponse
*/
        $response = $offlineUserDataJobServiceClient->addOfflineUserDataJobOperations(
            AddOfflineUserDataJobOperationsRequest::build(
                $offlineUserDataJobResourceName,
                self::buildOfflineUserDataJobOperations()
            )->setEnablePartialFailure(true)
        );

        // Prints the status message if any partial failure error is returned.
        // Note: The details of each partial failure error are not printed here, you can refer to
        // the example HandlePartialFailure.php to learn more.
        if ($response->hasPartialFailureError()) {
            // Extracts the partial failure from the response status.
            $partialFailure = GoogleAdsFailures::fromAny(
                $response->getPartialFailureError()->getDetails()->getIterator()->current()
            );
            printf(
                "%d partial failure error(s) occurred: %s.%s",
                count($partialFailure->getErrors()),
                $response->getPartialFailureError()->getMessage(),
                PHP_EOL
            );
        } else {
            print 'The operations are added to the offline user data job.' . PHP_EOL;
        }

        if ($runJob === false) {
            printf(
                "Not running offline user data job '%s', as requested.%s",
                $offlineUserDataJobResourceName,
                PHP_EOL
            );
            return;
        }

        // Issues an asynchronous request to run the offline user data job for executing all added
        // operations. The result is OperationResponse. Visit the OperationResponse.php file for
        // more details.
        $offlineUserDataJobServiceClient->runOfflineUserDataJob(
            RunOfflineUserDataJobRequest::build($offlineUserDataJobResourceName)
        );

        // Offline user data jobs may take 6 hours or more to complete, so instead of waiting
        // for the job to complete, retrieves and displays the job status once. If the job is
        // completed successfully, prints information about the user list. Otherwise, prints the
        // query to use to check the job again later.
        self::checkJobStatus($googleAdsClient, $customerId, $offlineUserDataJobResourceName);
    }
      

Python

def add_users_to_customer_match_user_list(
    client: GoogleAdsClient,
    customer_id: str,
    user_list_resource_name: str,
    run_job: bool,
    offline_user_data_job_id: Optional[str],
    ad_user_data_consent: Optional[str],
    ad_personalization_consent: Optional[str],
) -> None:
    """Uses Customer Match to create and add users to a new user list.

    Args:
        client: The Google Ads client.
        customer_id: The ID for the customer that owns the user list.
        user_list_resource_name: The resource name of the user list to which to
            add users.
        run_job: If true, runs the OfflineUserDataJob after adding operations.
            Otherwise, only adds operations to the job.
        offline_user_data_job_id: ID of an existing OfflineUserDataJob in the
            PENDING state. If None, a new job is created.
        ad_user_data_consent: The consent status for ad user data for all
            members in the job.
        ad_personalization_consent: The personalization consent status for ad
            user data for all members in the job.
    """
    # Creates the OfflineUserDataJobService client.
    offline_user_data_job_service_client: OfflineUserDataJobServiceClient = (
        client.get_service("OfflineUserDataJobService")
    )
    offline_user_data_job_resource_name: str

    if offline_user_data_job_id:
        # Reuses the specified offline user data job.
        offline_user_data_job_resource_name = (
            offline_user_data_job_service_client.offline_user_data_job_path(
                customer_id, offline_user_data_job_id
            )
        )
    else:
        # Creates a new offline user data job.
        offline_user_data_job: OfflineUserDataJob = client.get_type(
            "OfflineUserDataJob"
        )
        offline_user_data_job.type_ = (
            client.enums.OfflineUserDataJobTypeEnum.CUSTOMER_MATCH_USER_LIST
        )
        offline_user_data_job.customer_match_user_list_metadata.user_list = (
            user_list_resource_name
        )

        # Specifies whether user consent was obtained for the data you are
        # uploading. For more details, see:
        # https://www.google.com/about/company/user-consent-policy
        if ad_user_data_consent:
            offline_user_data_job.customer_match_user_list_metadata.consent.ad_user_data = client.enums.ConsentStatusEnum[
                ad_user_data_consent
            ]
        if ad_personalization_consent:
            offline_user_data_job.customer_match_user_list_metadata.consent.ad_personalization = client.enums.ConsentStatusEnum[
                ad_personalization_consent
            ]

        # Issues a request to create an offline user data job.
        create_offline_user_data_job_response: (
            CreateOfflineUserDataJobResponse
        ) = offline_user_data_job_service_client.create_offline_user_data_job(
            customer_id=customer_id, job=offline_user_data_job
        )
        offline_user_data_job_resource_name = (
            create_offline_user_data_job_response.resource_name
        )
        print(
            "Created an offline user data job with resource name: "
            f"'{offline_user_data_job_resource_name}'."
        )

    # Issues a request to add the operations to the offline user data job.

    # Best Practice: This example only adds a few operations, so it only sends
    # one AddOfflineUserDataJobOperations request. If your application is adding
    # a large number of operations, split the operations into batches and send
    # multiple AddOfflineUserDataJobOperations requests for the SAME job. See
    # https://developers.google.com/google-ads/api/docs/remarketing/audience-types/customer-match#customer_match_considerations
    # and https://developers.google.com/google-ads/api/docs/best-practices/quotas#user_data
    # for more information on the per-request limits.
    request: AddOfflineUserDataJobOperationsRequest = client.get_type(
        "AddOfflineUserDataJobOperationsRequest"
    )
    request.resource_name = offline_user_data_job_resource_name
    request.operations = build_offline_user_data_job_operations(client)
    request.enable_partial_failure = True

    # Issues a request to add the operations to the offline user data job.
    response: AddOfflineUserDataJobOperationsResponse = (
        offline_user_data_job_service_client.add_offline_user_data_job_operations(
            request=request
        )
    )

    # Prints the status message if any partial failure error is returned.
    # Note: the details of each partial failure error are not printed here.
    # Refer to the error_handling/handle_partial_failure.py example to learn
    # more.
    # Extracts the partial failure from the response status.
    partial_failure: Union[status_pb2.Status, None] = getattr(
        response, "partial_failure_error", None
    )
    if getattr(partial_failure, "code", None) != 0:
        error_details: Iterable[Any, None] = getattr(
            partial_failure, "details", []
        )
        for error_detail in error_details:
            failure_message: GoogleAdsFailure = client.get_type(
                "GoogleAdsFailure"
            )
            # Retrieve the class definition of the GoogleAdsFailure instance
            # in order to use the "deserialize" class method to parse the
            # error_detail string into a protobuf message object.
            failure_object: GoogleAdsFailure = type(
                failure_message
            ).deserialize(error_detail.value)
            errors: Iterable[GoogleAdsError] = failure_object.errors

            for error in errors:
                print(
                    "A partial failure at index "
                    f"{error.location.field_path_elements[0].index} occurred.\n"
                    f"Error message: {error.message}\n"
                    f"Error code: {error.error_code}"
                )

    print("The operations are added to the offline user data job.")

    if not run_job:
        print(
            "Not running offline user data job "
            f"'{offline_user_data_job_resource_name}', as requested."
        )
        return

    # Issues a request to run the offline user data job for executing all
    # added operations.
    offline_user_data_job_service_client.run_offline_user_data_job(
        resource_name=offline_user_data_job_resource_name
    )

    # Retrieves and displays the job status.
    check_job_status(client, customer_id, offline_user_data_job_resource_name)
      

Ruby

def add_users_to_customer_match_user_list(client, customer_id, run_job, user_list, job_id, ad_user_data_consent, ad_personalization_consent)
  offline_user_data_service = client.service.offline_user_data_job

  job_name = if job_id.nil?
    # Creates the offline user data job.
    offline_user_data_job = client.resource.offline_user_data_job do |job|
      job.type = :CUSTOMER_MATCH_USER_LIST
      job.customer_match_user_list_metadata =
        client.resource.customer_match_user_list_metadata do |m|
          m.user_list = user_list

          if !ad_user_data_consent.nil? || !ad_personalization_consent.nil?
            m.consent = client.resource.consent do |c|
              # Specifies whether user consent was obtained for the data you are
              # uploading. For more details, see:
              # https://www.google.com/about/company/user-consent-policy
              unless ad_user_data_consent.nil?
                c.ad_user_data = ad_user_data_consent
              end
              unless ad_personalization_consent.nil?
                c.ad_personalization = ad_personalization_consent
              end
            end
          end
        end
    end

    # Issues a request to create the offline user data job.
    response = offline_user_data_service.create_offline_user_data_job(
      customer_id: customer_id,
      job: offline_user_data_job,
    )
    offline_user_data_job_resource_name = response.resource_name
    puts "Created an offline user data job with resource name: " \
      "#{offline_user_data_job_resource_name}"

    offline_user_data_job_resource_name
  else
    client.path.offline_user_data_job(customer_id, job_id)
  end

  # Issues a request to add the operations to the offline user data job. This
  # example only adds a few operations, so it only sends one
  # AddOfflineUserDataJobOperations request.  If your application is adding a
  # large number of operations, split the operations into batches and send
  # multiple AddOfflineUserDataJobOperations requests for the SAME job. See
  # https://developers.google.com/google-ads/api/docs/remarketing/audience-types/customer-match#customer_match_considerations
  # and https://developers.google.com/google-ads/api/docs/best-practices/quotas#user_data
  # for more information on the per-request limits.
  response = offline_user_data_service.add_offline_user_data_job_operations(
    resource_name: offline_user_data_job_resource_name,
    enable_partial_failure: true,
    operations: build_offline_user_data_job_operations(client),
  )

  # Prints errors if any partial failure error is returned.
  if response.partial_failure_error
    failures = client.decode_partial_failure_error(response.partial_failure_error)
    failures.each do |failure|
      failure.errors.each do |error|
        human_readable_error_path = error
          .location
          .field_path_elements
          .map { |location_info|
            if location_info.index
              "#{location_info.field_name}[#{location_info.index}]"
            else
              "#{location_info.field_name}"
            end
          }.join(" > ")

        errmsg =  "error occured while adding operations " \
          "#{human_readable_error_path}" \
          " with value: #{error.trigger.string_value}" \
          " because #{error.message.downcase}"
        puts errmsg
      end
    end
  end
  puts "The operations are added to the offline user data job."

  unless run_job
    puts "Not running offline user data job #{job_name}, as requested."
    return
  end

  # Issues an asynchronous request to run the offline user data job
  # for executing all added operations.
  response = offline_user_data_service.run_offline_user_data_job(
    resource_name: offline_user_data_job_resource_name
  )
  puts "Asynchronous request to execute the added operations started."
  puts "Waiting until operation completes."

  # Offline user data jobs may take 6 hours or more to complete, so instead of
  # waiting for the job to complete, retrieves and displays the job status
  # once. If the job is completed successfully, prints information about the
  # user list. Otherwise, prints the query to use to check the job again later.
  check_job_status(
    client,
    customer_id,
    offline_user_data_job_resource_name,
  )
end
      

Perl

sub add_users_to_customer_match_user_list {
  my ($api_client, $customer_id, $run_job, $user_list_resource_name,
    $offline_user_data_job_id, $ad_personalization_consent,
    $ad_user_data_consent)
    = @_;

  my $offline_user_data_job_service = $api_client->OfflineUserDataJobService();

  my $offline_user_data_job_resource_name = undef;
  if (!defined $offline_user_data_job_id) {
    # Create a new offline user data job.
    my $offline_user_data_job =
      Google::Ads::GoogleAds::V25::Resources::OfflineUserDataJob->new({
        type                          => CUSTOMER_MATCH_USER_LIST,
        customerMatchUserListMetadata =>
          Google::Ads::GoogleAds::V25::Common::CustomerMatchUserListMetadata->
          new({
            userList => $user_list_resource_name
          })});

    # Add consent information to the job if specified.
    if ($ad_personalization_consent or $ad_user_data_consent) {
      my $consent = Google::Ads::GoogleAds::V25::Common::Consent->new({});
      if ($ad_personalization_consent) {
        $consent->{adPersonalization} = $ad_personalization_consent;
      }
      if ($ad_user_data_consent) {
        $consent->{adUserData} = $ad_user_data_consent;
      }
      # Specify whether user consent was obtained for the data you are uploading.
      # See https://www.google.com/about/company/user-consent-policy for details.
      $offline_user_data_job->{customerMatchUserListMetadata}{consent} =
        $consent;
    }

    # Issue a request to create the offline user data job.
    my $create_offline_user_data_job_response =
      $offline_user_data_job_service->create({
        customerId => $customer_id,
        job        => $offline_user_data_job
      });
    $offline_user_data_job_resource_name =
      $create_offline_user_data_job_response->{resourceName};
    printf
      "Created an offline user data job with resource name: '%s'.\n",
      $offline_user_data_job_resource_name;
  } else {
    # Reuse the specified offline user data job.
    $offline_user_data_job_resource_name =
      Google::Ads::GoogleAds::V25::Utils::ResourceNames::offline_user_data_job(
      $customer_id, $offline_user_data_job_id);
  }

  # Issue a request to add the operations to the offline user data job.
  # This example only adds a few operations, so it only sends one AddOfflineUserDataJobOperations
  # request. If your application is adding a large number of operations, split
  # the operations into batches and send multiple AddOfflineUserDataJobOperations
  # requests for the SAME job. See
  # https://developers.google.com/google-ads/api/docs/remarketing/audience-types/customer-match#customer_match_considerations
  # and https://developers.google.com/google-ads/api/docs/best-practices/quotas#user_data
  # for more information on the per-request limits.
  my $user_data_job_operations = build_offline_user_data_job_operations();
  my $response                 = $offline_user_data_job_service->add_operations(
    {
      resourceName         => $offline_user_data_job_resource_name,
      enablePartialFailure => "true",
      operations           => $user_data_job_operations
    });

  # Print the status message if any partial failure error is returned.
  # Note: The details of each partial failure error are not printed here, you can
  # refer to the example handle_partial_failure.pl to learn more.
  if ($response->{partialFailureError}) {
    # Extract the partial failure from the response status.
    my $partial_failure = $response->{partialFailureError}{details}[0];
    printf "Encountered %d partial failure errors while adding %d operations " .
      "to the offline user data job: '%s'. Only the successfully added " .
      "operations will be executed when the job runs.\n",
      scalar @{$partial_failure->{errors}}, scalar @$user_data_job_operations,
      $response->{partialFailureError}{message};
  } else {
    printf "Successfully added %d operations to the offline user data job.\n",
      scalar @$user_data_job_operations;
  }

  if (!defined $run_job) {
    print
"Not running offline user data job $offline_user_data_job_resource_name, as requested.\n";
    return;
  }

  # Issue an asynchronous request to run the offline user data job for executing
  # all added operations.
  my $operation_response = $offline_user_data_job_service->run({
    resourceName => $offline_user_data_job_resource_name
  });

  # Offline user data jobs may take 6 hours or more to complete, so instead of waiting
  # for the job to complete, this example retrieves and displays the job status once.
  # If the job is completed successfully, it prints information about the user list.
  # Otherwise, it prints, the query to use to check the job status again later.
  check_job_status($api_client, $customer_id,
    $offline_user_data_job_resource_name);
}
      

curl

הסרת משתמשים ספציפיים באמצעות מזהים

כדי להסיר משתמשים ספציפיים:

  • מגדירים את המאפיין remove ב-OfflineUserDataJobOperation כך שיהיה שווה לאובייקט UserData.

  • מוסיפים אובייקט UserIdentifier אחד או יותר לשדה החוזר user_identifiers[]. אפשר להשתמש במזהה משתמש אחד כדי להסיר משתמש מרשימה, גם אם נשלח יותר ממזהה אחד שתואם למשתמש.

בדיקה אם יש כשלים חלקיים

כשמוסיפים פעולות למשימה באמצעות AddOfflineUserDataJobOperations, אפשר להפעיל כשל חלקי על ידי הגדרת השדה enable_partial_failure לערך true ב-AddOfflineUserDataJobOperationsRequest.

אם מופעלת האפשרות 'כשל חלקי', פעולות שנכשלות באימות מתועדות בשדה partial_failure_error בתגובה, ואילו פעולות תקינות מתווספות לעבודה. אם הכישלון החלקי מושבת (ברירת המחדל), כל פעולה שנכשלת באימות גורמת לכישלון של הבקשה כולה. פרטים נוספים זמינים במדריך בנושא כשל חלקי.

חשוב לבדוק אם יש partial_failure_error בתגובה כשמופעל כשל חלקי. אם כל הפעולות נכשלות באימות, אף אחת מהן לא תתווסף למשימה, והשדה partial_failure_error יכיל את כל שגיאות הפעולה. אם תפעילו את RunOfflineUserDataJob, המשימה תסתיים מיד עם הסטטוס SUCCESS כי אין לה פעולות לעיבוד.

הסרה של כל הנתונים מהרשימה בבת אחת

כדי להסיר את כל המשתמשים מרשימה, מגדירים את remove_all לערך true ב-OfflineUserDataJobOperation, ואז שולחים בקשת RunOfflineUserDataJob עם שם המשאב שמשויך לפעולה remove_all.

בניגוד לפעולות remove נפרדות, אפשר לשלב פעולת remove_all עם פעולות create עוקבות באותו ה-job, בתנאי ש-remove_all היא הפעולה הראשונה ב-job. אם לא, הפעלת העבודה תחזיר שגיאה INVALID_OPERATION_ORDER. כדי להחליף את כל החברים ברשימת משתמשים בחברים חדשים, צריך להגדיר את הפעולות ב-AddOfflineUserDataJobOperationsRequest ברצף הבא:

  1. מגדירים את remove_all לערך true ב-OfflineUserDataJobOperation.

  2. לכל חבר חדש, מוסיפים פעולת create ומגדירים את UserData שלו ב-OfflineUserDataJobOperation.

פעולות remove_all מתבצעות מדי שעה, ויכולות להימשך עד 24 שעות.

המלצות לרענון רשימות לקוחות

אתם יכולים לאחזר המלצות מסוג REFRESH_CUSTOMER_MATCH_LIST כדי לזהות רשימות של לקוחות שלא עודכנו כבר זמן מה. האפשרות הזו שימושית במיוחד אם אתם מפרסמים צד שלישי שמאפשר למשתמשים שלו לנהל רשימות לקוחות.

מידע נוסף על עבודה עם המלצות זמין במדריך בנושא ציון האופטימיזציה וההמלצות.

הסרת רשימה

משתמשים ב-method‏ UserListService.MutateUserLists כדי לשלוח פעולת remove באמצעות שם המשאב של רשימת המשתמשים שרוצים להסיר.

עדכון רשימה באמצעות UserDataService

ל-UserDataService יש מגבלה של 10 פעולות ו-100 user_identifiers בסך הכול לכל בקשה, ולכן היא מתאימה יותר לעדכונים קטנים. לדוגמה, אם לכל אחד מהאובייקטים UserData יש מאפיין UserIdentifier אחד ל-hashed_email ומאפיין UserIdentifier נוסף ל-hashed_phone_number, הבקשה יכולה להכיל לכל היותר 50 אובייקטים UserData.

ה-UserDataService מכיל את ה-method‏ UploadUserData, שמקבל UploadUserDataRequest. בנוסף ל-customer_id, הפונקציה UploadUserDataRequest מקבלת רשימה של פעולות ליצירת אנשי קשר ושדה חובה בשם customer_match_user_list_metadata, שמאוכלס בשם המשאב של רשימת הרימרקטינג לטירגוט.

קודם כל, יוצרים מכונה של UploadUserDataRequest ומאכלסים את customer_id ו-customer_match_user_list_metadata:

Java

// Creates a request to add user data operations to the user list.
String userListResourceName =
    ResourceNames.userList(customerId, userListId);
UploadUserDataRequest.Builder uploadUserDataRequest =
    UploadUserDataRequest.newBuilder()
        .setCustomerId(String.valueOf(customerId))
        .setCustomerMatchUserListMetadata(
            CustomerMatchUserListMetadata.newBuilder()
                .setUserList(userListResourceName)
                .setConsent(
                    Consent.newBuilder()
                        .setAdUserData(ConsentStatus.GRANTED)
                        .setAdPersonalization(ConsentStatus.GRANTED)
                        .build())
                .build());

כדי להעלות את הפרטים ליצירת קשר של המשתמשים, מגדירים את CrmBasedUserListInfo.upload_key_type ל-CONTACT_INFO.

קודם מוסיפים את הפעולות לאובייקט UploadUserDataRequest. כל פעולה מכילה שדה create שמאוכלס באובייקטים מסוג UserData, שמכילים מופע אחד או יותר של UserIdentifier. כל UserIdentifier מכיל פריט אחד של פרטים אישיים מזהים או יכול להיות אחד מכמה סוגים שונים, שכל אחד מהם מתואר בקטעים הבאים.

כדי להעלות כתובות אימייל של לקוחות, יוצרים UserDataOperation חדש ומאכלסים את השדה create שלו באובייקט UserData. האובייקט UserData מקבל רשימה של user_identifiers. לפני שמאכלסים את השדה hashed_email, צריך לנרמל (להסיר רווחים לבנים ולהמיר לאותיות קטנות) ולגבב ב-SHA-256 כל כתובת אימייל:

Java

ImmutableList<String> EMAILS =
    ImmutableList.of(
        "client1@example.com",
        "client2@example.com",
        " Client3@example.com ");

// Normalize and hash email addresses using the SHA-256 hashing algorithm.
List<UserDataOperation> userDataOperations =
    new ArrayList<>(EMAILS.size());
for (String email : EMAILS) {
  String normalizedEmail = email.trim().toLowerCase();
  UserDataOperation userDataOperation =
      UserDataOperation.newBuilder()
          .setCreate(
              UserData.newBuilder()
                  .addUserIdentifiers(
                      UserIdentifier.newBuilder()
                          .setHashedEmail(toSHA256String(normalizedEmail))
                          .build())
                  .build())
          .build();
  userDataOperations.add(userDataOperation);
}
uploadUserDataRequest.addAllOperations(userDataOperations);

העלאת address_info של משתמשים דומה להעלאת כתובות אימייל של משתמשים. עם זאת, במקום להעביר hashed_email, מאכלסים את השדה address_info באובייקט OfflineUserAddressInfo שמכיל את הפרטים הבאים של המשתמש: first_name,‏ last_name,‏ country_code ו-postal_code. כמו כתובות אימייל, first_name ו-last_name נחשבים לפרטים אישיים מזהים, וצריך לנרמל ולגבב אותם לפני ההעלאה.

Java

String firstName = "Alex";
String lastName = "Quinn";
String countryCode = "US";
String postalCode = "94045";

String normalizedFirstName = firstName.trim().toLowerCase();
String normalizedLastName = lastName.trim().toLowerCase();

UserIdentifier userIdentifierWithAddress =
    UserIdentifier.newBuilder()
        .setAddressInfo(
            OfflineUserAddressInfo.newBuilder()
                // First and last name must be normalized and hashed.
                .setHashedFirstName(toSHA256String(normalizedFirstName))
                .setHashedLastName(toSHA256String(normalizedLastName))
                // Country code and zip code are sent in plaintext.
                .setCountryCode(countryCode)
                .setPostalCode(postalCode)
                .build())
        .build();

UserDataOperation userDataOperation =
    UserDataOperation.newBuilder()
        .setCreate(
            UserData.newBuilder()
                .addUserIdentifiers(userIdentifierWithAddress)
                .build())
        .build();
uploadUserDataRequest.addOperations(userDataOperation);

אחרי שמוסיפים פעולות למופע UploadUserDataRequest, מפעילים את השיטה uploadUserData ב-UserDataServiceClient כדי לשלוח את הבקשה לשרת Google Ads API. כדי לבדוק אם הבקשה הצליחה, בודקים את מספר הפעולות שהתקבלו ואת זמן ההעלאה באובייקט התגובה. חשוב לזכור שיכולות לעבור כמה שעות עד שהרשימה תתמלא בחברים.

Java

// Creates the user data service client.
try (UserDataServiceClient userDataServiceClient =
    googleAdsClient.getLatestVersion().createUserDataServiceClient()) {
  // Adds operations to the user list based on the user data type.
  UploadUserDataResponse response =
      userDataServiceClient.uploadUserData(uploadUserDataRequest.build());

  // Logs the results. It may take several hours for the list to be
  // populated with members.
  System.out.printf(
      "Received %d operations at %s%n",
      response.getReceivedOperationsCount(),
      response.getUploadDateTime());
}

שינוי רמת הטירגוט של הרשימה

אם אתם צריכים לשנות את רמת הטירגוט של הרשימה, למשל מטירגוט ברמת קבוצת המודעות לטירגוט ברמת הקמפיין, עיינו במדריך לשינוי רמות הטירגוט.

בדיקת הביצועים של הרשימה

כדי לאסוף נתוני ביצועים של פלחים של קהל היעד, שולחים בקשת חיפוש למשאב ad_group_audience_view או campaign_audience_view. לדוגמה, אתם יכולים לנתח את metrics.conversions או את metrics.cost_per_conversion כדי לקבוע אם טירגוט של פלח ספציפי של קהל היעד מגדיל את מספר ההמרות, ואז להתאים את הצעות המחיר בהתאם.

SELECT
  ad_group.id,
  ad_group_criterion.criterion_id,
  ad_group_criterion.resource_name,
  metrics.conversions,
  metrics.cost_per_conversion
FROM ad_group_audience_view
WHERE segments.date DURING LAST_30_DAYS

מומלץ להמתין לפחות שבועיים לפני שמבצעים אופטימיזציה של הצעות המחיר על סמך נפח התנועה לחשבון.