Джава
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.ads.googleads.examples.extensions;
import static com.google.ads.googleads.examples.utils.CodeSampleHelper.getPrintableDateTime;
import com.beust.jcommander.Parameter;
import com.google.ads.googleads.examples.utils.ArgumentNames;
import com.google.ads.googleads.examples.utils.CodeSampleParams;
import com.google.ads.googleads.lib.GoogleAdsClient;
import com.google.ads.googleads.v14.common.MatchingFunction;
import com.google.ads.googleads.v14.common.Operand;
import com.google.ads.googleads.v14.common.Operand.ConstantOperand;
import com.google.ads.googleads.v14.enums.FeedOriginEnum.FeedOrigin;
import com.google.ads.googleads.v14.enums.MatchingFunctionOperatorEnum.MatchingFunctionOperator;
import com.google.ads.googleads.v14.enums.PlaceholderTypeEnum.PlaceholderType;
import com.google.ads.googleads.v14.errors.GoogleAdsError;
import com.google.ads.googleads.v14.errors.GoogleAdsException;
import com.google.ads.googleads.v14.resources.CustomerFeed;
import com.google.ads.googleads.v14.resources.Feed;
import com.google.ads.googleads.v14.resources.Feed.PlacesLocationFeedData;
import com.google.ads.googleads.v14.resources.Feed.PlacesLocationFeedData.OAuthInfo;
import com.google.ads.googleads.v14.services.CustomerFeedOperation;
import com.google.ads.googleads.v14.services.CustomerFeedServiceClient;
import com.google.ads.googleads.v14.services.FeedOperation;
import com.google.ads.googleads.v14.services.FeedServiceClient;
import com.google.ads.googleads.v14.services.MutateCustomerFeedsResponse;
import com.google.ads.googleads.v14.services.MutateFeedsResponse;
import com.google.common.collect.ImmutableList;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* Adds a feed that syncs feed items from a Business Profile account and associates the feed with a
* customer.
*/
public class AddBusinessProfileLocationExtensions {
// The required scope for setting the OAuth info.
private final String GOOGLE_ADS_SCOPE = "https://www.googleapis.com/auth/adwords";
// The maximum number of CustomerFeed ADD operation attempts to make before throwing an exception.
private static final int MAX_CUSTOMER_FEED_ADD_ATTEMPTS = 10;
private static class AddBusinessProfileLocationExtensionsParams extends CodeSampleParams {
@Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
private Long customerId;
@Parameter(names = ArgumentNames.BUSINESS_PROFILE_EMAIL_ADDRESS, required = true)
private String businessProfileEmailAddress;
@Parameter(names = ArgumentNames.BUSINESS_ACCOUNT_IDENTIFIER)
private String businessAccountIdentifier;
@Parameter(names = ArgumentNames.BUSINESS_PROFILE_ACCESS_TOKEN, required = true)
private String businessProfileAccessToken;
}
public static void main(String[] args) throws InterruptedException, IOException {
AddBusinessProfileLocationExtensionsParams params =
new AddBusinessProfileLocationExtensionsParams();
if (!params.parseArguments(args)) {
// Either pass the required parameters for this example on the command line, or insert them
// into the code here. See the parameter class definition above for descriptions.
params.customerId = Long.parseLong("INSERT_CUSTOMER_ID_HERE");
params.businessProfileEmailAddress = "INSERT_BUSINESS_PROFILE_EMAIL_ADDRESS_HERE";
params.businessAccountIdentifier = "INSERT_BUSINESS_ACCOUNT_IDENTIFIER_HERE";
params.businessProfileAccessToken = "INSERT_BUSINESS_PROFILE_ACCESS_TOKEN_HERE";
}
GoogleAdsClient googleAdsClient = null;
try {
googleAdsClient = GoogleAdsClient.newBuilder().fromPropertiesFile().build();
} catch (FileNotFoundException fnfe) {
System.err.printf(
"Failed to load GoogleAdsClient configuration from file. Exception: %s%n", fnfe);
System.exit(1);
} catch (IOException ioe) {
System.err.printf("Failed to create GoogleAdsClient. Exception: %s%n", ioe);
System.exit(1);
}
try {
new AddBusinessProfileLocationExtensions()
.runExample(
googleAdsClient,
params.customerId,
params.businessProfileEmailAddress,
params.businessAccountIdentifier,
params.businessProfileAccessToken);
} catch (GoogleAdsException gae) {
// GoogleAdsException is the base class for most exceptions thrown by an API request.
// Instances of this exception have a message and a GoogleAdsFailure that contains a
// collection of GoogleAdsErrors that indicate the underlying causes of the
// GoogleAdsException.
System.err.printf(
"Request ID %s failed due to GoogleAdsException. Underlying errors:%n",
gae.getRequestId());
int i = 0;
for (GoogleAdsError googleAdsError : gae.getGoogleAdsFailure().getErrorsList()) {
System.err.printf(" Error %d: %s%n", i++, googleAdsError);
}
System.exit(1);
}
}
/**
* Runs the example.
*
* @param googleAdsClient the Google Ads API client.
* @param customerId the client customer ID.
* @param businessProfileEmailAddress email address associated with the Business Profile account.
* @param businessAccountIdentifier the account number of the Business Profile account (optional).
* @param businessProfileAccessToken the access token created using the 'AdWords' scope and the
* client ID and client secret of with the Cloud project associated with the Business Profile
* account.
* @throws GoogleAdsException if an API request failed with one or more service errors.
* @throws InterruptedException if the Thread.sleep operation is interrupted.
*/
private void runExample(
GoogleAdsClient googleAdsClient,
long customerId,
String businessProfileEmailAddress,
String businessAccountIdentifier,
String businessProfileAccessToken)
throws InterruptedException {
// Creates a PlacesLocationFeedData object to identify the Business Profile account, specify
// location filters, and provide authorization for Google Ads to retrieve locations from the
// account on behalf of the user identified by businessProfileEmailAddress.
PlacesLocationFeedData.Builder placesLocationFeedData =
PlacesLocationFeedData.newBuilder()
.setEmailAddress(businessProfileEmailAddress)
// Used to filter Business Profile listings by labels. If entries exist in
// label_filters, only listings that have at least one of the labels set are
// candidates to be synchronized into FeedItems. If no entries exist in
// label_filters, then all listings are candidates for syncing.
.addLabelFilters("Stores in New York")
// Sets the authentication info to be able to connect Google Ads to the Business Profile
// account.
.setOauthInfo(
OAuthInfo.newBuilder()
.setHttpMethod("GET")
.setHttpRequestUrl(GOOGLE_ADS_SCOPE)
.setHttpAuthorizationHeader("Bearer " + businessProfileAccessToken)
.build());
if (businessAccountIdentifier != null) {
placesLocationFeedData.setBusinessAccountId(businessAccountIdentifier);
}
// Creates a feed that will sync to the Business Profile account. Do not add FeedAttributes to
// this object as Google Ads will add them automatically because this will be a system generated
// feed.
Feed.Builder businessProfileFeed =
Feed.newBuilder()
.setName("Business Profile feed #" + getPrintableDateTime())
// Configures the location feed populated from Business Profile Locations.
.setPlacesLocationFeedData(placesLocationFeedData)
// Since this feed's feed items will be managed by Google,
// you must set its origin to GOOGLE.
.setOrigin(FeedOrigin.GOOGLE);
FeedOperation operation = FeedOperation.newBuilder().setCreate(businessProfileFeed).build();
try (FeedServiceClient feedServiceClient =
googleAdsClient.getLatestVersion().createFeedServiceClient()) {
// Adds the feed. Since it is a system generated feed, Google Ads will automatically:
// 1. Set up the FeedAttributes on the feed.
// 2. Set up a FeedMapping that associates the FeedAttributes of the feed
// with the placeholder fields of the LOCATION placeholder type.
MutateFeedsResponse response =
feedServiceClient.mutateFeeds(Long.toString(customerId), ImmutableList.of(operation));
String businessProfileFeedResourceName = response.getResults(0).getResourceName();
System.out.printf(
"Business Profile feed created with resource name: %s%n",
businessProfileFeedResourceName);
// Adds a CustomerFeed that associates the feed with this customer for
// the LOCATION placeholder type.
CustomerFeed customerFeed =
CustomerFeed.newBuilder()
.setFeed(businessProfileFeedResourceName)
.addPlaceholderTypes(PlaceholderType.LOCATION)
// Creates a matching function that will always evaluate to true.
.setMatchingFunction(
MatchingFunction.newBuilder()
.addLeftOperands(
Operand.newBuilder()
.setConstantOperand(
ConstantOperand.newBuilder().setBooleanValue(true).build())
.build())
.setFunctionString("IDENTITY(true)")
.setOperator(MatchingFunctionOperator.IDENTITY)
.build())
.build();
CustomerFeedOperation customerFeedOperation =
CustomerFeedOperation.newBuilder().setCreate(customerFeed).build();
try (CustomerFeedServiceClient customerFeedServiceClient =
googleAdsClient.getLatestVersion().createCustomerFeedServiceClient()) {
// After the completion of the Feed ADD operation above the added feed will not be available
// for usage in a CustomerFeed until the sync between the Google Ads and Business Profile
// accounts
// completes. The loop below will retry adding the CustomerFeed up to ten times with an
// exponential back-off policy.
String addedCustomerFeed = null;
int numberOfAttempts = 0;
do {
numberOfAttempts++;
try {
MutateCustomerFeedsResponse customerFeedsResponse =
customerFeedServiceClient.mutateCustomerFeeds(
Long.toString(customerId), ImmutableList.of(customerFeedOperation));
addedCustomerFeed = customerFeedsResponse.getResults(0).getResourceName();
System.out.printf("Customer feed created with resource name: %s%n", addedCustomerFeed);
} catch (GoogleAdsException gae) {
// Waits using exponential backoff policy.
long sleepSeconds = (long) Math.scalb(5, numberOfAttempts);
// Exits the loop early if sleepSeconds grows too large in the event that
// MAX_CUSTOMER_FEED_ADD_ATTEMPTS is set too high.
if (sleepSeconds > (long) Math.scalb(5, 10)) {
break;
}
System.out.printf(
"Attempt #%d to add the CustomerFeed was not successful. "
+ "Waiting %d seconds before trying again.%n",
numberOfAttempts, sleepSeconds);
Thread.sleep(sleepSeconds * 1000);
}
} while (numberOfAttempts < MAX_CUSTOMER_FEED_ADD_ATTEMPTS && addedCustomerFeed == null);
if (addedCustomerFeed == null) {
throw new RuntimeException(
"Could not create the CustomerFeed after "
+ MAX_CUSTOMER_FEED_ADD_ATTEMPTS
+ " attempts. Please retry "
+ "the CustomerFeed ADD operation later.");
}
// OPTIONAL: Create a CampaignFeed to specify which FeedItems to use at the Campaign
// level.
// OPTIONAL: Create an AdGroupFeed for even more fine grained control over
// which feed items are used at the AdGroup level.
}
}
}
}
С#
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using CommandLine;
using Google.Ads.Gax.Examples;
using Google.Ads.GoogleAds.Lib;
using Google.Ads.GoogleAds.V14.Common;
using Google.Ads.GoogleAds.V14.Errors;
using Google.Ads.GoogleAds.V14.Resources;
using Google.Ads.GoogleAds.V14.Services;
using Google.Api.Gax;
using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using static Google.Ads.GoogleAds.V14.Common.Operand.Types;
using static Google.Ads.GoogleAds.V14.Enums.FeedOriginEnum.Types;
using static Google.Ads.GoogleAds.V14.Enums.MatchingFunctionOperatorEnum.Types;
using static Google.Ads.GoogleAds.V14.Enums.PlaceholderTypeEnum.Types;
using static Google.Ads.GoogleAds.V14.Resources.Feed.Types;
using static Google.Ads.GoogleAds.V14.Resources.Feed.Types.PlacesLocationFeedData.Types;
namespace Google.Ads.GoogleAds.Examples.V14
{
/// <summary>
/// This code example adds a feed that syncs feed items from a Business Profile account
/// and associates the feed with a customer.
/// </summary>
public class AddBusinessProfileLocationExtensions : ExampleBase
{
/// <summary>
/// Command line options for running the <see cref="AddBusinessProfileLocationExtensions"/>
/// example.
/// </summary>
public class Options : OptionsBase
{
/// <summary>
/// The customer ID for which the call is made.
/// </summary>
[Option("customerId", Required = true, HelpText =
"The customer ID for which the call is made.")]
public long CustomerId { get; set; }
/// <summary>
/// The Business Profile login email address.
/// </summary>
[Option("businessProfileEmailAddress", Required = true, HelpText =
"The Business Profile login email address.")]
public string BusinessProfileEmailAddress { get; set; }
/// <summary>
/// The Business Profile account identifier.
/// </summary>
[Option("businessAccountId", Required = false, HelpText =
"The Business Profile account identifier.")]
public string BusinessAccountId { get; set; }
/// <summary>
/// The OAuth2 access token for the Business Profile account.
/// </summary>
[Option("businessProfileAccessToken", Required = false, HelpText =
"The OAuth2 access token for the Business Profile account.")]
public string BusinessProfileAccessToken { get; set; }
}
/// <summary>
/// Main method, to run this code example as a standalone application.
/// </summary>
/// <param name="args">The command line arguments.</param>
public static void Main(string[] args)
{
Options options = ExampleUtilities.ParseCommandLine<Options>(args);
AddBusinessProfileLocationExtensions codeExample =
new AddBusinessProfileLocationExtensions();
Console.WriteLine(codeExample.Description);
codeExample.Run(new GoogleAdsClient(), options.CustomerId,
options.BusinessProfileEmailAddress,
options.BusinessAccountId, options.BusinessProfileAccessToken);
}
// The required scope for setting the OAuth info.
private const string GOOGLE_ADS_SCOPE = "https://www.googleapis.com/auth/adwords";
// The maximum number of attempts to make to retrieve the FeedMappings before throwing an
// exception.
private const int MAX_FEEDMAPPING_RETRIEVAL_ATTEMPTS = 10;
/// <summary>
/// Returns a description about the code example.
/// </summary>
public override string Description =>
"This code example adds a feed that syncs feed items from a Business Profile " +
"account and associates the feed with a customer.";
/// <summary>
/// Runs the code example.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="businessProfileEmailAddress">The Business Profile login email address.
/// </param>
/// <param name="businessAccountId">The Business Profile account identifier.</param>
/// <param name="businessProfileAccessToken">The OAuth2 access token for the Business
/// Profile account.</param>
public void Run(GoogleAdsClient client, long customerId,
string businessProfileEmailAddress, string businessAccountId,
string businessProfileAccessToken)
{
try
{
if (string.IsNullOrEmpty(businessProfileAccessToken))
{
businessProfileAccessToken = client.Config.OAuth2AccessToken;
}
string businessProfileFeedResourceName = CreateBusinessProfileFeed(client, customerId, businessProfileEmailAddress,
businessAccountId, businessProfileAccessToken);
// After the completion of the Feed ADD operation above the added feed will not be
// available for usage in a CustomerFeed until the FeedMappings are created.
// We will wait with an exponential back-off policy until the feedmappings have
// been created.
WaitForBusinessProfileFeedToBeReady(client, customerId, businessProfileFeedResourceName);
CreateCustomerFeed(client, customerId, businessProfileFeedResourceName);
}
catch (GoogleAdsException e)
{
Console.WriteLine("Failure:");
Console.WriteLine($"Message: {e.Message}");
Console.WriteLine($"Failure: {e.Failure}");
Console.WriteLine($"Request ID: {e.RequestId}");
throw;
}
}
/// <summary>
/// Creates the Business Profile feed.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="businessProfileEmailAddress">The Business Profile login email address.
/// </param>
/// <param name="businessAccountId">The Business Profile account ID.</param>
/// <param name="businessProfileAccessToken">The OAuth2 access token for the Business
/// Profile account.</param>
/// <returns>ID of the newly created Business Profile feed.</returns>
private static string CreateBusinessProfileFeed(GoogleAdsClient client, long customerId,
string businessProfileEmailAddress, string businessAccountId,
string businessProfileAccessToken)
{
// Optional: Delete all existing location extension feeds. This is an optional step,
// and is required for this code example to run correctly more than once.
// 1. Google Ads only allows one location extension feed per email address.
// 2. A Google Ads account cannot have a location extension feed and an affiliate
// location extension feed at the same time.
DeleteLocationExtensionFeeds(client, customerId);
// Get the FeedServiceClient.
FeedServiceClient feedService = client.GetService(Services.V14.FeedService);
// Creates a feed that will sync to the Business Profile account specified by
// businessProfileEmailAddress. Do not add FeedAttributes to this object as Google Ads
// will add them automatically because this will be a system generated feed.
Feed businessProfileFeed = new Feed()
{
Name = "Business Profile feed #" + ExampleUtilities.GetRandomString(),
PlacesLocationFeedData = new PlacesLocationFeedData()
{
EmailAddress = businessProfileEmailAddress,
// If the EmailAddress is for a Business Profile manager instead of the
// Business Profile account owner, then set BusinessAccountId to the Google+
// Page ID of a location for which the manager has access. This information is
// available through the Business Profile API. See
// https://developers.google.com/my-business/reference/rest/v4/accounts.locations#locationkey
// for details.
BusinessAccountId = string.IsNullOrEmpty(businessAccountId) ?
null : businessAccountId,
// Used to filter Business Profile listings by labels. If entries exist in
// label_filters, only listings that have at least one of the labels set are
// candidates to be synchronized into FeedItems. If no entries exist in
// label_filters, then all listings are candidates for syncing.
LabelFilters = { "Stores in New York" },
// Sets the authentication info to be able to connect Google Ads to the
// Business Profile account.
OauthInfo = new OAuthInfo()
{
HttpMethod = "GET",
HttpRequestUrl = GOOGLE_ADS_SCOPE,
HttpAuthorizationHeader = $"Bearer {businessProfileAccessToken}"
},
},
// Since this feed's feed items will be managed by Google,
// you must set its origin to GOOGLE.
Origin = FeedOrigin.Google
};
FeedOperation operation = new FeedOperation()
{
Create = businessProfileFeed
};
// Adds the feed.
MutateFeedsResponse response =
feedService.MutateFeeds(customerId.ToString(), new[] { operation });
// Displays the results.
string businessProfileFeedResourceName = response.Results[0].ResourceName;
Console.WriteLine($"Business Profile feed created with resource name: " +
$"{businessProfileFeedResourceName}.");
return businessProfileFeedResourceName;
}
/// <summary>
/// Deletes the old location extension feeds.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
private static void DeleteLocationExtensionFeeds(GoogleAdsClient client, long customerId)
{
// To delete a location extension feed, you need to
// 1. Delete the CustomerFeed so that the location extensions from the feed stop
// serving.
// 2. Delete the feed so that Google Ads will no longer sync from the Business Profile
// account.
CustomerFeed[] oldCustomerFeeds =
GetLocationExtensionCustomerFeeds(client, customerId);
if (oldCustomerFeeds.Length != 0)
{
DeleteCustomerFeeds(client, customerId, oldCustomerFeeds);
}
Feed[] feeds = GetLocationExtensionFeeds(client, customerId);
if (feeds.Length != 0)
{
RemoveFeeds(client, customerId, feeds);
}
}
/// <summary>
/// Gets the location extension feeds.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <returns>The list of location extension feeds.</returns>
private static Feed[] GetLocationExtensionFeeds(GoogleAdsClient client, long customerId)
{
List<Feed> feeds = new List<Feed>();
GoogleAdsServiceClient googleAdsService = client.GetService(
Services.V14.GoogleAdsService);
// Create the query.
string query = $"SELECT feed.resource_name, feed.status, " +
$"feed.places_location_feed_data.email_address, " +
$"feed.affiliate_location_feed_data.chain_ids " +
$" from feed where feed.status = ENABLED";
PagedEnumerable<SearchGoogleAdsResponse, GoogleAdsRow> result =
googleAdsService.Search(customerId.ToString(), query);
foreach (GoogleAdsRow row in result)
{
// A location extension feed can be identified by checking whether the
// PlacesLocationFeedData field is set (Location extensions feeds) or
// AffiliateLocationFeedData field is set (Affiliate location extension feeds)
Feed feed = row.Feed;
if (feed.PlacesLocationFeedData != null || feed.AffiliateLocationFeedData != null)
{
feeds.Add(feed);
}
}
return feeds.ToArray();
}
/// <summary>
/// Removes the feeds.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="feeds">The list of feeds to remove.</param>
private static void RemoveFeeds(GoogleAdsClient client, long customerId, Feed[] feeds)
{
List<FeedOperation> operations = new List<FeedOperation>();
foreach (Feed feed in feeds)
{
FeedOperation operation = new FeedOperation()
{
Remove = feed.ResourceName,
};
operations.Add(operation);
}
FeedServiceClient feedService = client.GetService(
Services.V14.FeedService);
feedService.MutateFeeds(customerId.ToString(), operations.ToArray());
}
private static CustomerFeed[] GetLocationExtensionCustomerFeeds(GoogleAdsClient client,
long customerId)
{
List<CustomerFeed> customerFeeds = new List<CustomerFeed>();
GoogleAdsServiceClient googleAdsService = client.GetService(
Services.V14.GoogleAdsService);
// Create the query. A location extension customer feed can be identified by filtering
// for placeholder_types=LOCATION (location extension feeds) or
// placeholder_types =AFFILIATE_LOCATION (affiliate location extension feeds)
string query = $"SELECT customer_feed.resource_name, customer_feed.feed, " +
$"customer_feed.status, customer_feed.matching_function.function_string from " +
$"customer_feed " +
$"WHERE customer_feed.placeholder_types CONTAINS " +
$"ANY(LOCATION, AFFILIATE_LOCATION) and customer_feed.status=ENABLED";
PagedEnumerable<SearchGoogleAdsResponse, GoogleAdsRow> result =
googleAdsService.Search(customerId.ToString(), query);
foreach (GoogleAdsRow row in result)
{
customerFeeds.Add(row.CustomerFeed);
}
return customerFeeds.ToArray();
}
/// <summary>
/// Deletes the customer feeds.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="customerFeeds">The customer feeds to delete.</param>
private static void DeleteCustomerFeeds(GoogleAdsClient client, long customerId,
CustomerFeed[] customerFeeds)
{
List<CustomerFeedOperation> operations = new List<CustomerFeedOperation>();
foreach (CustomerFeed customerFeed in customerFeeds)
{
CustomerFeedOperation operation = new CustomerFeedOperation()
{
Remove = customerFeed.ResourceName,
};
operations.Add(operation);
}
CustomerFeedServiceClient feedService = client.GetService(
Services.V14.CustomerFeedService);
feedService.MutateCustomerFeeds(customerId.ToString(), operations.ToArray());
}
/// <summary>
/// Gets the Business Profile feed mapping.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="businessProfileFeedResourceName">The Business Profile feed resource name.
/// </param>
/// <returns>The newly created feed mapping.</returns>
private static FeedMapping GetBusinessProfileFeedMapping(GoogleAdsClient client,
long customerId, string businessProfileFeedResourceName)
{
// Get the GoogleAdsService.
GoogleAdsServiceClient googleAdsService = client.GetService(
Services.V14.GoogleAdsService);
// Create the query.
string query = $"SELECT feed_mapping.resource_name, feed_mapping.status FROM " +
$"feed_mapping WHERE feed_mapping.feed = '{businessProfileFeedResourceName}' and " +
$"feed_mapping.status = ENABLED and feed_mapping.placeholder_type = LOCATION" +
$" LIMIT 1";
// Issue a search request.
PagedEnumerable<SearchGoogleAdsResponse, GoogleAdsRow> result =
googleAdsService.Search(customerId.ToString(), query);
// Display the results.
GoogleAdsRow googleAdsRow = result.FirstOrDefault();
return (googleAdsRow == null) ? null : googleAdsRow.FeedMapping;
}
/// <summary>
/// Waits for the Business Profile feed to be ready.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="businessProfileFeedResourceName">The Business Profile feed resource name.
/// </param>
private static void WaitForBusinessProfileFeedToBeReady(GoogleAdsClient client,
long customerId, string businessProfileFeedResourceName)
{
int numAttempts = 0;
while (numAttempts < MAX_FEEDMAPPING_RETRIEVAL_ATTEMPTS)
{
// Once you create a feed, Google's servers will setup the feed by creating feed
// attributes and feedmapping. Once the feedmapping is created, it is ready to be
// used for creating customer feed.
// This process is asynchronous, so we wait until the feed mapping is created,
// peforming exponential backoff.
FeedMapping feedMapping = GetBusinessProfileFeedMapping(client,
customerId, businessProfileFeedResourceName);
if (feedMapping == null)
{
numAttempts++;
int sleepSeconds = (int)(5 * Math.Pow(2, numAttempts));
Console.WriteLine($"Checked: #{numAttempts} time(s). Business Profile feed " +
$"is not ready yet. Waiting {sleepSeconds} seconds before trying again.");
Thread.Sleep(sleepSeconds * 1000);
}
else
{
Console.WriteLine($"Business Profile Feed {businessProfileFeedResourceName} " +
$"is now ready.");
return;
}
}
throw new RpcException(new Status(StatusCode.DeadlineExceeded,
$"Business Profile Feed is not ready after {MAX_FEEDMAPPING_RETRIEVAL_ATTEMPTS} " +
$"retries."));
}
/// <summary>
/// Creates the customer feed.
/// </summary>
/// <param name="client">The client.</param>
/// <param name="customerId">The customer identifier.</param>
/// <param name="businessProfileFeedResourceName">The Business Profile feed resource name.
/// </param>
private static void CreateCustomerFeed(GoogleAdsClient client, long customerId,
string businessProfileFeedResourceName)
{
// Get the CustomerFeedService.
CustomerFeedServiceClient customerFeedService = client.GetService(
Services.V14.CustomerFeedService);
// Adds a CustomerFeed that associates the feed with this customer for
// the LOCATION placeholder type.
CustomerFeed customerFeed = new CustomerFeed()
{
Feed = businessProfileFeedResourceName,
PlaceholderTypes = { PlaceholderType.Location },
MatchingFunction = new MatchingFunction()
{
LeftOperands =
{
new Operand()
{
ConstantOperand = new ConstantOperand()
{
BooleanValue = true
}
}
},
// Specify the function string as IDENTITY(true) to mark this feed as enabled.
FunctionString = "IDENTITY(true)",
Operator = MatchingFunctionOperator.Identity
},
};
CustomerFeedOperation operation = new CustomerFeedOperation()
{
Create = customerFeed
};
MutateCustomerFeedsResponse customerFeedsResponse =
customerFeedService.MutateCustomerFeeds(
customerId.ToString(), new[] { operation });
// Displays the result.
string addedCustomerFeed = customerFeedsResponse.Results[0].ResourceName;
Console.WriteLine($"Customer feed created with resource name: {addedCustomerFeed}.");
return;
}
}
}
PHP
<?php
/**
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace Google\Ads\GoogleAds\Examples\Extensions;
require __DIR__ . '/../../vendor/autoload.php';
use GetOpt\GetOpt;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentNames;
use Google\Ads\GoogleAds\Examples\Utils\ArgumentParser;
use Google\Ads\GoogleAds\Examples\Utils\Helper;
use Google\Ads\GoogleAds\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V14\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V14\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V14\GoogleAdsException;
use Google\Ads\GoogleAds\V14\Common\MatchingFunction;
use Google\Ads\GoogleAds\V14\Common\Operand;
use Google\Ads\GoogleAds\V14\Common\Operand\ConstantOperand;
use Google\Ads\GoogleAds\V14\Enums\FeedOriginEnum\FeedOrigin;
use Google\Ads\GoogleAds\V14\Enums\MatchingFunctionOperatorEnum\MatchingFunctionOperator;
use Google\Ads\GoogleAds\V14\Enums\PlaceholderTypeEnum\PlaceholderType;
use Google\Ads\GoogleAds\V14\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V14\Resources\CustomerFeed;
use Google\Ads\GoogleAds\V14\Resources\Feed;
use Google\Ads\GoogleAds\V14\Resources\Feed\PlacesLocationFeedData;
use Google\Ads\GoogleAds\V14\Resources\Feed\PlacesLocationFeedData\OAuthInfo;
use Google\Ads\GoogleAds\V14\Services\CustomerFeedOperation;
use Google\Ads\GoogleAds\V14\Services\FeedOperation;
use Google\ApiCore\ApiException;
/**
* This example adds a feed that syncs feed items from a Business Profile account
* and associates the feed with a customer.
*/
class AddBusinessProfileLocationExtensions
{
private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
private const BUSINESS_PROFILE_EMAIL = 'INSERT_BUSINESS_PROFILE_EMAIL_HERE';
private const BUSINESS_PROFILE_ACCESS_TOKEN = 'INSERT_BUSINESS_PROFILE_ACCESS_TOKEN_HERE';
private const BUSINESS_ACCOUNT_IDENTIFIER = 'INSERT_BUSINESS_ACCOUNT_IDENTIFIER_HERE';
// The required scope for setting the OAuth info.
private const GOOGLE_ADS_SCOPE = 'https://www.googleapis.com/auth/adwords';
// The maximum number of customer feed ADD operation attempts to make before throwing an
// exception.
private const MAX_CUSTOMER_FEED_ADD_ATTEMPTS = 10;
private const POLL_FREQUENCY_SECONDS = 5;
public static function main()
{
// Either pass the required parameters for this example on the command line, or insert them
// into the constants above.
$options = (new ArgumentParser())->parseCommandArguments([
ArgumentNames::CUSTOMER_ID => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::BUSINESS_PROFILE_EMAIL => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::BUSINESS_PROFILE_ACCESS_TOKEN => GetOpt::REQUIRED_ARGUMENT,
ArgumentNames::BUSINESS_ACCOUNT_IDENTIFIER => GetOpt::REQUIRED_ARGUMENT
]);
// Generate a refreshable OAuth2 credential for authentication.
$oAuth2Credential = (new OAuth2TokenBuilder())->fromFile()->build();
// Construct a Google Ads client configured from a properties file and the
// OAuth2 credentials above.
$googleAdsClient = (new GoogleAdsClientBuilder())->fromFile()
->withOAuth2Credential($oAuth2Credential)
->build();
try {
self::runExample(
$googleAdsClient,
$options[ArgumentNames::CUSTOMER_ID] ?: self::CUSTOMER_ID,
$options[ArgumentNames::BUSINESS_PROFILE_EMAIL]
?: self::BUSINESS_PROFILE_EMAIL,
$options[ArgumentNames::BUSINESS_PROFILE_ACCESS_TOKEN]
?: self::BUSINESS_PROFILE_ACCESS_TOKEN,
$options[ArgumentNames::BUSINESS_ACCOUNT_IDENTIFIER]
?: self::BUSINESS_ACCOUNT_IDENTIFIER
);
} catch (GoogleAdsException $googleAdsException) {
printf(
"Request with ID '%s' has failed.%sGoogle Ads failure details:%s",
$googleAdsException->getRequestId(),
PHP_EOL,
PHP_EOL
);
foreach ($googleAdsException->getGoogleAdsFailure()->getErrors() as $error) {
/** @var GoogleAdsError $error */
printf(
"\t%s: %s%s",
$error->getErrorCode()->getErrorCode(),
$error->getMessage(),
PHP_EOL
);
}
exit(1);
} catch (ApiException $apiException) {
printf(
"ApiException was thrown with message '%s'.%s",
$apiException->getMessage(),
PHP_EOL
);
exit(1);
}
}
/**
* Runs the example.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the client customer ID
* @param string $businessProfileEmail the email address associated with the Business
* Profile account
* @param string $businessProfileAccessToken the access token created using the 'AdWords' scope
* and the client ID and client secret of with the Cloud project associated with the
* Business Profile account
* @param string $businessAccountIdentifier the account number of the Business Profile account
*/
public static function runExample(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $businessProfileEmail,
string $businessProfileAccessToken,
string $businessAccountIdentifier
) {
$businessProfileFeedResourceName = self::createFeed(
$googleAdsClient,
$customerId,
$businessProfileEmail,
$businessProfileAccessToken,
$businessAccountIdentifier
);
self::createCustomerFeed($googleAdsClient, $customerId, $businessProfileFeedResourceName);
// OPTIONAL: Create a campaign feed to specify which feed items to use at the campaign
// level.
// OPTIONAL: Create an ad group feed for even more fine grained control over which feed
// items are used at the ad group level.
}
/**
* Creates a location feed that will sync to the Business Profile account specified by
* `$businessProfileEmailAddress`. Do not add feed attributes to this object as Google Ads will
* add them automatically because this will be a system generated feed.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the client customer ID
* @param string $businessProfileEmail the email address associated with the Business
* Profile account
* @param string $businessProfileAccessToken the access token created using the 'AdWords' scope
* and the client ID and client secret of with the Cloud project associated with the
* Business Profile account
* @param string $businessAccountIdentifier the account number of the Business Profile account
* @return string the feed's resource name
*/
private static function createFeed(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $businessProfileEmail,
string $businessProfileAccessToken,
string $businessAccountIdentifier
) {
$businessProfileFeed = new Feed([
'name' => 'Business Profile feed #' . Helper::getPrintableDatetime(),
'origin' => FeedOrigin::GOOGLE,
'places_location_feed_data' => new PlacesLocationFeedData([
'email_address' => $businessProfileEmail,
'business_account_id' => $businessAccountIdentifier,
// Used to filter Business Profile listings by labels. If entries exist in
// label_filters, only listings that have at least one of the labels set are
// candidates to be synchronized into FeedItems. If no entries exist in
// label_filters, then all listings are candidates for syncing.
'label_filters' => ['Stores in New York'],
// Sets the authentication info to be able to connect Google Ads to the Business
// Profile account.
'oauth_info' => new OAuthInfo([
'http_method' => 'GET',
'http_request_url' => self::GOOGLE_ADS_SCOPE,
'http_authorization_header' => 'Bearer ' . $businessProfileAccessToken
])
])
]);
// Creates a feed operation.
$feedOperation = new FeedOperation();
$feedOperation->setCreate($businessProfileFeed);
// Issues a mutate request to add the feed and print its information.
// Since it is a system generated feed, Google Ads will automatically:
// 1. Set up the feed attributes on the feed.
// 2. Set up a feed mapping that associates the feed attributes of the feed with the
// placeholder fields of the LOCATION placeholder type.
$feedServiceClient = $googleAdsClient->getFeedServiceClient();
$response = $feedServiceClient->mutateFeeds(
$customerId,
[$feedOperation]
);
$businessProfileFeedResourceName = $response->getResults()[0]->getResourceName();
printf(
"Business Profile feed created with resource name: '%s'.%s",
$businessProfileFeedResourceName,
PHP_EOL
);
return $businessProfileFeedResourceName;
}
/**
* Creates a customer feed to attach the previously created Business Profile feed to the
* specified customer ID.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the client customer ID
* @param string $businessProfileFeedResourceName the feed's resource name to be used to create
* a customer feed
*/
private static function createCustomerFeed(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $businessProfileFeedResourceName
) {
// Creates a customer feed that associates the feed with this customer for the LOCATION
// placeholder type.
$customerFeed = new CustomerFeed([
'feed' => $businessProfileFeedResourceName,
'placeholder_types' => [PlaceholderType::LOCATION],
// Creates a matching function that will always evaluate to true.
'matching_function' => new MatchingFunction([
'left_operands' => [new Operand([
'constant_operand' => new ConstantOperand(['boolean_value' => true])
])],
'function_string' => 'IDENTITY(true)',
'operator' => MatchingFunctionOperator::IDENTITY
])
]);
// Creates a customer feed operation.
$customerFeedOperation = new CustomerFeedOperation();
$customerFeedOperation->setCreate($customerFeed);
// After the completion of the feed ADD operation above the added feed will not be available
// for usage in a customer feed until the sync between the Google Ads and Business Profile
// accounts completes. The loop below will retry adding the customer feed up to ten times
// with an exponential back-off policy.
$numberOfAttempts = 0;
$addedCustomerFeed = null;
$customerFeedServiceClient = $googleAdsClient->getCustomerFeedServiceClient();
do {
$numberOfAttempts++;
try {
// Issues a mutate request to add a customer feed and print its information if the
// request succeeded.
$addedCustomerFeed = $customerFeedServiceClient->mutateCustomerFeeds(
$customerId,
[$customerFeedOperation]
);
printf(
"Customer feed created with resource name: '%s'.%s",
$addedCustomerFeed->getResults()[0]->getResourceName(),
PHP_EOL
);
} catch (GoogleAdsException $googleAdsException) {
// Waits using exponential backoff policy.
$sleepSeconds = self::POLL_FREQUENCY_SECONDS * pow(2, $numberOfAttempts);
// Exits the loop early if $sleepSeconds grows too large in the event that
// MAX_CUSTOMER_FEED_ADD_ATTEMPTS is set too high.
if (
$sleepSeconds > self::POLL_FREQUENCY_SECONDS
* pow(2, self::MAX_CUSTOMER_FEED_ADD_ATTEMPTS)
) {
break;
}
printf(
"Attempt #%d to add the customer feed was not successful."
. " Waiting %d seconds before trying again.%s",
$numberOfAttempts,
$sleepSeconds,
PHP_EOL
);
sleep($sleepSeconds);
}
} while (
$numberOfAttempts < self::MAX_CUSTOMER_FEED_ADD_ATTEMPTS
&& is_null($addedCustomerFeed)
);
if (is_null($addedCustomerFeed)) {
throw new \RuntimeException(
'Could not create the customer feed after ' . self::MAX_CUSTOMER_FEED_ADD_ATTEMPTS
. ' attempts. Please retry the customer feed ADD operation later.'
);
}
}
}
AddBusinessProfileLocationExtensions::main();
Питон
#!/usr/bin/env python
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Adds a feed that syncs feed items from a Business Profile account.
The feed will also be associated with a customer.
"""
import argparse
import sys
import time
from uuid import uuid4
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
MAX_CUSTOMER_FEED_ADD_ATTEMPTS = 9
DEFAULT_OAUTH2_SCOPE = "https://www.googleapis.com/auth/adwords"
def main(
client,
customer_id,
business_profile_email,
business_account_id,
business_profile_access_token,
):
"""Adds a feed that syncs feed items from a Business Profile account.
The feed will also be associated with a customer.
Args:
client: An initialized GoogleAdsClient instance.
customer_id: The Google Ads customer ID.
business_profile_email: The email address associated with the Business
Profile account.
business_account_id: The account ID of the managed business.
business_profile_access_token: The access token created using the
'AdWords' scope and the client ID and client secret of with the Cloud
project associated with the Business Profile account.
"""
# Get the FeedService and CustomerFeedService clients.
feed_service = client.get_service("FeedService")
customer_feed_service = client.get_service("CustomerFeedService")
# Create a feed operation and configure the new feed.
# The feed will sync to the Business Profile account specified by
# business_profile_email. Do not add FeedAttributes to this object as Google Ads
# will add them automatically because this will be a system generated feed.
# See here for more details:
# https://developers.google.com/google-ads/api/docs/location-extensions/google-ads-location-extensions
feed_operation = client.get_type("FeedOperation")
business_profile_feed = feed_operation.create
business_profile_feed.name = f"Business Profile Feed #{uuid4()}"
# Configure the location feed populated from Business Profile Locations.
business_profile_feed.places_location_feed_data.email_address = (
business_profile_email
)
if business_account_id is not None:
business_profile_feed.places_location_feed_data.business_account_id = (
business_account_id
)
# Used to filter Business Profile listings by labels. If entries exist in
# label_filters, only listings that have at least one of the labels set are
# candidates to be synchronized into FeedItems. If no entries exist in
# label_filters, then all listings are candidates for syncing.
business_profile_feed.places_location_feed_data.label_filters.append(
"Stores in New York"
)
# Set the authentication info to be able to connect Google Ads to the
# Business Profile account.
business_profile_feed.places_location_feed_data.oauth_info.http_method = (
"GET"
)
business_profile_feed.places_location_feed_data.oauth_info.http_request_url = (
DEFAULT_OAUTH2_SCOPE
)
business_profile_feed.places_location_feed_data.oauth_info.http_authorization_header = (
f"Bearer {business_profile_access_token}"
)
# Since this feed's feed items will be managed by Google, you must set its
# origin to GOOGLE.
business_profile_feed.origin = client.enums.FeedOriginEnum.GOOGLE
# Optional: Delete all existing location extension feeds. This is an
# optional step, and is required for this code example to run correctly
# more than once; Google Ads only allows one location extension feed
# per email address, and a Google Ads account cannot have a location
# extension feed and an affiliate location extension feed at the same
# time.
delete_location_extension_feeds(client, customer_id)
# Add the feed. Since it is a system generated feed, Google Ads will
# automatically:
# 1. Set up the FeedAttributes on the feed.
# 2. Set up a FeedMapping that associates the FeedAttributes of the feed
# with the placeholder fields of the LOCATION placeholder type.
feed_response = feed_service.mutate_feeds(
customer_id=customer_id, operations=[feed_operation]
)
feed_resource_name = feed_response.results[0].resource_name
print(
"Business Profile feed created with resource name "
f"'{feed_resource_name}'."
)
# After the completion of the Feed ADD operation above the added feed
# will not be available for usage in a CustomerFeed until the sync
# between the Google Ads and Business Profile accounts completes.
# This process is asynchronous, so we wait until the feed mapping is
# created, performing exponential backoff.
customer_feed_resource_name = None
number_of_attempts = 0
while number_of_attempts < MAX_CUSTOMER_FEED_ADD_ATTEMPTS:
feed_mapping = get_business_profile_feed_mapping(
client, customer_id, feed_resource_name
)
if feed_mapping is None:
number_of_attempts += 1
sleep_seconds = 5 * (2 ** number_of_attempts)
print(
f"Attempt #{number_of_attempts} was not successful. "
f"Waiting {sleep_seconds}s before trying again."
)
time.sleep(sleep_seconds)
else:
customer_feed_resource_name = feed_mapping.resource_name
print(f"Business Profile feed {feed_resource_name} is now ready.")
break
if customer_feed_resource_name is None:
print(
"Could not create the CustomerFeed after "
f"{MAX_CUSTOMER_FEED_ADD_ATTEMPTS} attempts. Please retry "
"the CustomerFeed ADD operation later."
)
sys.exit(1)
else:
# Create a CustomerFeed operation and configure the CustomerFeed to
# associate the feed with this customer for the LOCATION placeholder
# type.
# OPTIONAL: Create a CampaignFeed to specify which FeedItems to use at
# the Campaign level.
# OPTIONAL: Create an AdGroupFeed for even more fine grained control
# over which feed items are used at the AdGroup level.
customer_feed_operation = client.get_type("CustomerFeedOperation")
customer_feed = customer_feed_operation.create
customer_feed.feed = feed_resource_name
customer_feed.placeholder_types.append(
client.enums.PlaceholderTypeEnum.LOCATION
)
# The function string "IDENTITY(true)" will enable this feed.
true_operand = client.get_type("Operand")
true_operand.constant_operand.boolean_value = True
customer_feed.matching_function.left_operands.append(true_operand)
customer_feed.matching_function.function_string = "IDENTITY(true)"
customer_feed.matching_function.operator = (
client.enums.MatchingFunctionOperatorEnum.IDENTITY
)
customer_feed_response = customer_feed_service.mutate_customer_feeds(
customer_id=customer_id, operations=[customer_feed_operation]
)
print(
"Customer feed created with resource name "
f"'{customer_feed_response.results[0].resource_name}'."
)
def delete_location_extension_feeds(client, customer_id):
"""Deletes the existing location extension feeds.
Args:
client: An initialized Google Ads API client.
customer_id: The Google Ads customer ID.
"""
# To delete a location extension feed, you need to:
# 1. Delete the CustomerFeed so that the location extensions from the feed
# stop serving.
# 2. Delete the feed so that Google Ads will no longer sync from the
# Business Profile account.
old_customer_feeds = get_location_extension_customer_feeds(
client, customer_id
)
if old_customer_feeds:
delete_customer_feeds(client, customer_id, old_customer_feeds)
old_feeds = get_location_extension_feeds(client, customer_id)
if old_feeds:
delete_feeds(client, customer_id, old_feeds)
def get_location_extension_customer_feeds(client, customer_id):
"""Gets the existing location extension customer feeds.
Args:
client: An initialized Google Ads API client.
customer_id: The Google Ads customer ID.
Returns:
A list of location extension feeds.
"""
googleads_service = client.get_service("GoogleAdsService")
# Create the query. A location extension customer feed can be identified by
# filtering for placeholder_types=LOCATION (location extension feeds) or
# placeholder_types=AFFILIATE_LOCATION (affiliate location extension feeds).
query = """
SELECT
customer_feed.resource_name,
customer_feed.feed,
customer_feed.status,
customer_feed.matching_function.function_string
FROM customer_feed
WHERE
customer_feed.placeholder_types CONTAINS ANY(LOCATION, AFFILIATE_LOCATION)
AND customer_feed.status = ENABLED"""
result = googleads_service.search(customer_id=customer_id, query=query)
return [row.customer_feed for row in result]
def get_location_extension_feeds(client, customer_id):
"""Gets the existing location extension feeds.
Args:
client: An initialized Google Ads API client.
customer_id: The Google Ads customer ID.
Returns:
A list of location extension feeds.
"""
googleads_service = client.get_service("GoogleAdsService")
# Create the query.
query = """
SELECT
feed.resource_name,
feed.status,
feed.places_location_feed_data.email_address,
feed.affiliate_location_feed_data.chain_ids
FROM feed
WHERE feed.status = ENABLED"""
result = googleads_service.search(customer_id=customer_id, query=query)
# A location extension feed can be identified by checking whether the
# places_location_feed_data field is set or the
# affiliate_location_feed_data field is set.
return [
row.feed
for row in result
if row.feed.places_location_feed_data
or row.feed.affiliate_location_feed_data
]
def delete_customer_feeds(client, customer_id, old_customer_feeds):
"""Removes the customer feeds.
Args:
client: An initialized Google Ads API client.
customer_id: The Google Ads customer ID.
old_customer_feeds: The list of customer feeds to delete.
"""
operations = []
customer_feed_service = client.get_service("CustomerFeedService")
for customer_feed in old_customer_feeds:
operation = client.get_type("CustomerFeedOperation")
operation.remove = customer_feed.resource_name
operations.append(operation)
customer_feed_service.mutate_customer_feeds(
customer_id=customer_id, operations=operations
)
def delete_feeds(client, customer_id, old_feeds):
"""Removes the specified feeds.
Args:
client: An initialized Google Ads API client.
customer_id: The Google Ads customer ID.
old_feeds: The list of feeds to delete.
"""
operations = []
feed_service = client.get_service("FeedService")
for feed in old_feeds:
operation = client.get_type("FeedOperation")
operation.remove = feed.resource_name
operations.append(operation)
feed_service.mutate_feeds(customer_id=customer_id, operations=operations)
def get_business_profile_feed_mapping(client, customer_id, feed_resource_name):
"""Gets a Business Profile Feed mapping.
Args:
client: An initialized Google Ads client.
customer_id: The customer ID for which the call is made.
feed_resource_name: The string Business Profile feed resource name.
Returns:
The requested FeedMapping, or None if it is not available.
"""
googleads_service = client.get_service("GoogleAdsService")
query = f"""
SELECT feed_mapping.resource_name, feed_mapping.status
FROM feed_mapping
WHERE
feed_mapping.feed = '{feed_resource_name}'
AND feed_mapping.status = ENABLED
AND feed_mapping.placeholder_type = LOCATION
LIMIT 1"""
result = googleads_service.search(customer_id=customer_id, query=query)
try:
return next(iter(result)).feed_mapping
except StopIteration:
return None
if __name__ == "__main__":
# GoogleAdsClient will read the google-ads.yaml configuration file in the
# home directory if none is specified.
googleads_client = GoogleAdsClient.load_from_storage(version="v14")
parser = argparse.ArgumentParser(
description="Adds a feed that syncs feed items from a Business Profile "
"account."
)
# The following argument(s) should be provided to run the example.
parser.add_argument(
"-c",
"--customer_id",
type=str,
required=True,
help="The Google Ads customer ID.",
)
parser.add_argument(
"-e",
"--business_profile_email",
type=str,
required=True,
help="The email address associated with the Business Profile account.",
)
parser.add_argument(
"-b",
"--business_account_id",
type=str,
required=False,
help="The account ID of the managed business.\n"
"If the email_address is for a Business Profile manager instead of the "
"Business Profile account owner, then set business_account_id to the"
"Google+ Page ID of a location for which the manager has access. This "
"information is available through the Business Profile API. See "
"https://developers.google.com/my-business/reference/rest/v4/accounts.locations#locationkey"
"for details.",
)
parser.add_argument(
"-t",
"--business_profile_access_token",
type=str,
required=False,
default=googleads_client.credentials.token,
help="If the business_profile_email above is the same user you used to "
"generate your Google Ads API refresh token, do not pass a value to "
"this argument.\nOtherwise, to obtain an access token for your "
"Business Profile account, run the "
"authenticate_in_standalone_application code example while logged in "
"as the same user as business_profile_email. Pass the "
"Access Token value to this argument.",
)
args = parser.parse_args()
try:
main(
googleads_client,
args.customer_id,
args.business_profile_email,
args.business_account_id,
args.business_profile_access_token,
)
except GoogleAdsException as ex:
print(
f"Request with ID '{ex.request_id}' failed with status "
f"'{ex.error.code().name}' and includes the following errors:"
)
for error in ex.failure.errors:
print(f"\tError with message '{error.message}'.")
if error.location:
for field_path_element in error.location.field_path_elements:
print(f"\t\tOn field: {field_path_element.field_name}")
sys.exit(1)
Рубин
#!/usr/bin/env ruby
# Encoding: utf-8
#
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example adds a feed that syncs feed items from a Business Profile
# account and associates the feed with a customer.
require 'optparse'
require 'google/ads/google_ads'
require 'date'
def add_business_profile_location_extensions(
customer_id,
business_profile_email_address,
business_profile_access_token,
business_account_identifier)
# GoogleAdsClient will read a config file from
# ENV['HOME']/google_ads_config.rb when called without parameters
client = Google::Ads::GoogleAds::GoogleAdsClient.new
business_profile_feed_resource_name = create_feed(
client,
customer_id,
business_profile_email_address,
business_profile_access_token,
business_account_identifier,
)
create_customer_feed(client, customer_id, business_profile_feed_resource_name)
end
def create_feed(
client,
customer_id,
business_profile_email_address,
business_profile_access_token,
business_account_identifier)
# Creates a feed operation.
operation = client.operation.create_resource.feed do |feed|
feed.name = "Business Profile feed #{(Time.new.to_f * 1000).to_i}"
feed.origin = :GOOGLE
feed.places_location_feed_data = client.resource.places_location_feed_data do |data|
data.email_address = business_profile_email_address
data.business_account_id = business_account_identifier
data.label_filters << "Stores in New York"
data.oauth_info = client.resource.o_auth_info do |oauth|
oauth.http_method = "GET"
oauth.http_request_url = "https://www.googleapis.com/auth/adwords"
oauth.http_authorization_header = "Bearer #{business_profile_access_token}"
end
end
end
# Issues a mutate request to add the feed and print its information.
# Since it is a system generated feed, Google Ads will automatically:
# 1. Set up the feed attributes on the feed.
# 2. Set up a feed mapping that associates the feed attributes of the feed with the
# placeholder fields of the LOCATION placeholder type.
response = client.service.feed.mutate_feeds(
customer_id: customer_id,
operations: [operation],
)
# Prints out the Business Profile feed resource name.
business_profile_feed_resource_name = response.results.first.resource_name
puts "Business Profile feed created with resource name: #{business_profile_feed_resource_name}"
business_profile_feed_resource_name
end
def create_customer_feed(
client,
customer_id,
business_profile_feed_resource_name)
# Creates a customer feed operation.
operation = client.operation.create_resource.customer_feed do |cf|
cf.feed = business_profile_feed_resource_name
cf.placeholder_types << :LOCATION
cf.matching_function = client.resource.matching_function do |m|
m.left_operands << client.resource.operand do |op|
op.constant_operand = client.resource.constant_operand do |co|
co.boolean_value = true
end
end
m.function_string = "IDENTITY(true)"
m.operator = :IDENTITY
end
end
# After the completion of the feed ADD operation above the added feed will
# not be available for usage in a customer feed until the sync between the
# Google Ads and Business Profile accounts completes. The loop below will
# retry adding the customer feed up to ten times with an exponential back-off
# policy.
number_of_attempts = 0
added_customer_feed = nil
customer_feed_service_client = client.service.customer_feed
loop do
number_of_attempts += 1
begin
# Issues a mutate request to add a customer feed and print its information
# if the request succeeded.
response = customer_feed_service_client.mutate_customer_feeds(
customer_id: customer_id,
operations: [operation]
)
puts "Customer feed created with resource name: " \
"#{response.results.first.resource_name}"
rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
# Waits using exponential backoff policy
sleep_seconds = POLL_FREQUENCY_SECONDS * (2 ** number_of_attempts)
puts "Attempt #{number_of_attempts} to add the customer feed was " \
"not successful. Waiting #{sleep_seconds} seconds before trying again."
sleep sleep_seconds
end
break if number_of_attempts >= MAX_CUSTOMER_FEED_ADD_ATTEMPTS || added_customer_feed
end
if added_customer_feed.nil?
raise "Could not create the customer feed after #{MAX_CUSTOMER_FEED_ADD_ATTEMPTS} " \
"attempts. Please retry the customer feed ADD operation later."
end
end
if __FILE__ == $0
# The maximum number of customer feed ADD operation attempts to make before
# throwing an exception.
MAX_CUSTOMER_FEED_ADD_ATTEMPTS = 10
POLL_FREQUENCY_SECONDS = 5
options = {}
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
options[:customer_id] = 'INSERT_CUSTOMER_ID_HERE'
options[:campaign_id] = 'INSERT_CAMPAIGN_ID_HERE'
OptionParser.new do |opts|
opts.banner = sprintf('Usage: %s [options]', File.basename(__FILE__))
opts.separator ''
opts.separator 'Options:'
opts.on('-C', '--customer-id CUSTOMER-ID', String, 'Customer ID') do |v|
options[:customer_id] = v
end
opts.on('-E', '--business-profile-email-address BUSINESS-PROFILE-EMAIL-ADDRESS',
String, 'Business Profile Email Address') do |v|
options[:business_profile_email_address] = v
end
opts.on('-T', '--business-profile-access-token BUSINESS-PROFILE-ACCESS-TOKEN', String,
'Business Profile Access Token') do |v|
options[:business_profile_access_token] = v
end
opts.on('-B', '--business-account-identifier BUSINESS-ACCOUNT-IDENTIFIER', String, 'Business Account Identifier') do |v|
options[:business_account_identifier] = v
end
opts.separator ''
opts.separator 'Help:'
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
end.parse!
begin
add_business_profile_location_extensions(
options.fetch(:customer_id).tr("-", ""),
options.fetch(:business_profile_email_address),
options.fetch(:business_profile_access_token),
options.fetch(:business_account_identifier),
)
rescue Google::Ads::GoogleAds::Errors::GoogleAdsError => e
e.failure.errors.each do |error|
STDERR.printf("Error with message: %s\n", error.message)
if error.location
error.location.field_path_elements.each do |field_path_element|
STDERR.printf("\tOn field: %s\n", field_path_element.field_name)
end
end
error.error_code.to_h.each do |k, v|
next if v == :UNSPECIFIED
STDERR.printf("\tType: %s\n\tCode: %s\n", k, v)
end
end
raise
end
end
Перл
#!/usr/bin/perl -w
#
# Copyright 2019, Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This example adds a feed that syncs feed items from a Business Profile account
# and associates the feed with a customer.
use strict;
use warnings;
use utf8;
use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Constants;
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::V14::Resources::Feed;
use Google::Ads::GoogleAds::V14::Resources::PlacesLocationFeedData;
use Google::Ads::GoogleAds::V14::Resources::OAuthInfo;
use Google::Ads::GoogleAds::V14::Resources::CustomerFeed;
use Google::Ads::GoogleAds::V14::Common::MatchingFunction;
use Google::Ads::GoogleAds::V14::Common::Operand;
use Google::Ads::GoogleAds::V14::Common::ConstantOperand;
use Google::Ads::GoogleAds::V14::Enums::FeedOriginEnum qw(GOOGLE);
use Google::Ads::GoogleAds::V14::Enums::PlaceholderTypeEnum qw(LOCATION);
use Google::Ads::GoogleAds::V14::Enums::MatchingFunctionOperatorEnum
qw(IDENTITY);
use Google::Ads::GoogleAds::V14::Services::FeedService::FeedOperation;
use
Google::Ads::GoogleAds::V14::Services::CustomerFeedService::CustomerFeedOperation;
use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
use Data::Uniqid qw(uniqid);
use Time::HiRes qw(sleep);
use constant MAX_CUSTOMER_FEED_ADD_ATTEMPTS => 10;
# The following parameter(s) should be provided to run the example. You can
# either specify these by changing the INSERT_XXX_ID_HERE values below, or on
# the command line.
#
# Parameters passed on the command line will override any parameters set in
# code.
#
# Running the example with -h will print the command line usage.
my $customer_id = "INSERT_CUSTOMER_ID_HERE";
my $business_profile_email = "INSERT_BUSINESS_PROFILE_EMAIL_HERE";
my $business_profile_account_id = "INSERT_BUSINESS_PROFILE_ACCOUNT_ID_HERE";
my $business_profile_access_token = "INSERT_BUSINESS_PROFILE_ACCESS_TOKEN_HERE";
sub add_business_profile_location_extensions {
my ($api_client, $customer_id, $business_profile_email,
$business_profile_account_id, $business_profile_access_token)
= @_;
# Create a feed that will sync to the Business Profile account specified by
# $business_profile_email. Do not add FeedAttributes to this object as Google Ads
# will add them automatically because this will be a system generated feed.
my $business_profile_feed = Google::Ads::GoogleAds::V14::Resources::Feed->new(
{
name => "Business Profile feed #" . uniqid(),
# Configure the location feed populated from Business Profile Locations.
placesLocationFeedData =>
Google::Ads::GoogleAds::V14::Resources::PlacesLocationFeedData->new({
emailAddress => $business_profile_email,
businessAccountId => $business_profile_account_id,
# Used to filter Business Profile listings by labels. If entries exist in
# label_filters, only listings that have at least one of the labels set are
# candidates to be synchronized into FeedItems. If no entries exist in
# label_filters, then all listings are candidates for syncing.
labelFilters => ["Stores in New York"],
# Set the authentication info to be able to connect Google Ads to the
# Business Profile account.
oauthInfo => Google::Ads::GoogleAds::V14::Resources::OAuthInfo->new({
httpMethod => "GET",
httpRequestUrl =>
Google::Ads::GoogleAds::Constants::DEFAULT_OAUTH2_SCOPE,
httpAuthorizationHeader => "Bearer " .
$business_profile_access_token
})}
),
# Since this feed's feed items will be managed by Google, you must set its
# origin to GOOGLE.
origin => GOOGLE
});
# Create a feed operation.
my $feed_operation =
Google::Ads::GoogleAds::V14::Services::FeedService::FeedOperation->new(
{create => $business_profile_feed});
# Add the feed. Since it is a system generated feed, Google Ads will automatically:
# 1. Set up the FeedAttributes on the feed.
# 2. Set up a FeedMapping that associates the FeedAttributes of the feed with the
# placeholder fields of the LOCATION placeholder type.
my $feeds_response = $api_client->FeedService()->mutate({
customerId => $customer_id,
operations => [$feed_operation]});
my $feed_resource_name = $feeds_response->{results}[0]{resourceName};
printf "Business Profile feed created with resource name: '%s'.\n",
$feed_resource_name;
# Add a CustomerFeed that associates the feed with this customer for the LOCATION
# placeholder type.
my $customer_feed = Google::Ads::GoogleAds::V14::Resources::CustomerFeed->new(
{
feed => $feed_resource_name,
placeholderTypes => LOCATION,
# Create a matching function that will always evaluate to true.
matchingFunction =>
Google::Ads::GoogleAds::V14::Common::MatchingFunction->new({
leftOperands => [
Google::Ads::GoogleAds::V14::Common::Operand->new({
constantOperand =>
Google::Ads::GoogleAds::V14::Common::ConstantOperand->new({
booleanValue => "true"
})})
],
functionString => "IDENTITY(true)",
operator => IDENTITY
})});
# Create a customer feed operation.
my $customer_feed_operation =
Google::Ads::GoogleAds::V14::Services::CustomerFeedService::CustomerFeedOperation
->new({create => $customer_feed});
# After the completion of the Feed ADD operation above the added feed will not be available
# for usage in a CustomerFeed until the sync between the Google Ads and Business Profile
# accounts completes. The loop below will retry adding the CustomerFeed up to ten times with an
# exponential back-off policy.
my $customer_feed_service = $api_client->CustomerFeedService();
my $customer_feed_resource_name = undef;
my $number_of_attempts = 0;
while ($number_of_attempts < MAX_CUSTOMER_FEED_ADD_ATTEMPTS) {
$number_of_attempts++;
my $customer_feeds_response = eval {
$customer_feed_service->mutate({
customerId => $customer_id,
operations => [$customer_feed_operation],
});
};
if ($@) {
# Wait using exponential backoff policy.
my $sleep_seconds = 5 * (2**$number_of_attempts);
# Exit the loop early if $sleep_seconds grows too large in the event that
# MAX_CUSTOMER_FEED_ADD_ATTEMPTS is set too high.
if ($sleep_seconds > 5 * (2**10)) {
last;
}
printf "Attempt #%d to add the CustomerFeed was not successful. " .
"Waiting %d seconds before trying again.\n",
$number_of_attempts, $sleep_seconds;
sleep($sleep_seconds);
} else {
$customer_feed_resource_name =
$customer_feeds_response->{results}[0]{resourceName};
printf "Customer feed created with resource name: '%s'.\n",
$customer_feed_resource_name;
last;
}
}
printf "Could not create the CustomerFeed after %d attempts. " .
"Please retry the CustomerFeed ADD operation later.",
MAX_CUSTOMER_FEED_ADD_ATTEMPTS
if not $customer_feed_resource_name;
# OPTIONAL: Create a CampaignFeed to specify which FeedItems to use at the Campaign level.
# OPTIONAL: Create an AdGroupFeed for even more fine grained control over which feed items
# are used at the AdGroup level.
return 1;
}
# Don't run the example if the file is being included.
if (abs_path($0) ne abs_path(__FILE__)) {
return 1;
}
# Get Google Ads Client, credentials will be read from ~/googleads.properties.
my $api_client = Google::Ads::GoogleAds::Client->new();
# By default examples are set to die on any server returned fault.
$api_client->set_die_on_faults(1);
# Parameters passed on the command line will override any parameters set in code.
GetOptions(
"customer_id=s" => \$customer_id,
"business_profile_email=s" => \$business_profile_email,
"business_profile_account_id=s" => \$business_profile_account_id,
"business_profile_access_token=s" => \$business_profile_access_token,
);
# Print the help message if the parameters are not initialized in the code nor
# in the command line.
pod2usage(2)
if not check_params($customer_id, $business_profile_email,
$business_profile_account_id, $business_profile_access_token);
# Call the example.
add_business_profile_location_extensions($api_client, $customer_id =~ s/-//gr,
$business_profile_email,
$business_profile_account_id, $business_profile_access_token);
=pod
=head1 NAME
add_business_profile_location_extensions
=head1 DESCRIPTION
This example adds a feed that syncs feed items from a Business Profile account
and associates the feed with a customer.
=head1 SYNOPSIS
add_business_profile_location_extensions.pl [options]
-help Show the help message.
-customer_id The Google Ads customer ID.
-business_profile_email The email address associated with the Business Profile
` account.
-business_profile_account_id The account ID of the managed business.
-business_profile_access_token The access token created using the 'AdWords' scope
and the client ID and client secret of with the
Cloud project associated with the Business Profile account.
=cut