Джава
// Copyright 2021 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.
package com.google.ads.googleads.examples.extensions;
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.v13.common.PromotionAsset;
import com.google.ads.googleads.v13.common.PromotionFeedItem;
import com.google.ads.googleads.v13.enums.AssetFieldTypeEnum.AssetFieldType;
import com.google.ads.googleads.v13.errors.GoogleAdsError;
import com.google.ads.googleads.v13.errors.GoogleAdsException;
import com.google.ads.googleads.v13.resources.AdGroup;
import com.google.ads.googleads.v13.resources.AdGroupAsset;
import com.google.ads.googleads.v13.resources.AdGroupExtensionSetting;
import com.google.ads.googleads.v13.resources.Asset;
import com.google.ads.googleads.v13.resources.Campaign;
import com.google.ads.googleads.v13.resources.CampaignAsset;
import com.google.ads.googleads.v13.resources.CampaignExtensionSetting;
import com.google.ads.googleads.v13.resources.ExtensionFeedItem;
import com.google.ads.googleads.v13.resources.FeedItem;
import com.google.ads.googleads.v13.services.AdGroupAssetOperation;
import com.google.ads.googleads.v13.services.AdGroupAssetServiceClient;
import com.google.ads.googleads.v13.services.AssetOperation;
import com.google.ads.googleads.v13.services.AssetServiceClient;
import com.google.ads.googleads.v13.services.CampaignAssetOperation;
import com.google.ads.googleads.v13.services.CampaignAssetServiceClient;
import com.google.ads.googleads.v13.services.GoogleAdsRow;
import com.google.ads.googleads.v13.services.GoogleAdsServiceClient;
import com.google.ads.googleads.v13.services.MutateAdGroupAssetResult;
import com.google.ads.googleads.v13.services.MutateAdGroupAssetsResponse;
import com.google.ads.googleads.v13.services.MutateAssetsResponse;
import com.google.ads.googleads.v13.services.MutateCampaignAssetResult;
import com.google.ads.googleads.v13.services.MutateCampaignAssetsResponse;
import com.google.ads.googleads.v13.services.SearchGoogleAdsStreamRequest;
import com.google.ads.googleads.v13.services.SearchGoogleAdsStreamResponse;
import com.google.ads.googleads.v13.utils.ResourceNames;
import com.google.api.gax.rpc.ServerStream;
import com.google.common.collect.ImmutableList;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/**
* Retrieves the full details of a Promotion Feed-based extension and creates a matching Promotion
* asset-based extension. The new Asset-based extension will then be associated with the same
* campaigns and ad groups as the original Feed-based extension. Finally, the Feed-based extension
* will be mutated to no longer serve.
* Once copied, you should remove the Feed-based extension; see
* RemoveEntireSitelinkCampaignExtensionSetting.java for an example.
*/
public class MigratePromotionFeedToAsset {
private static class MigratePromotionFeedToAssetParams extends CodeSampleParams {
@Parameter(names = ArgumentNames.CUSTOMER_ID, required = true)
private Long customerId;
@Parameter(names = ArgumentNames.FEED_ITEM_ID, required = true)
private Long extensionFeedItemId;
}
public static void main(String[] args) {
MigratePromotionFeedToAssetParams params = new MigratePromotionFeedToAssetParams();
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.extensionFeedItemId = Long.parseLong("INSERT_EXTENSION_FEED_ITEM_ID_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 MigratePromotionFeedToAsset()
.runExample(googleAdsClient, params.customerId, params.extensionFeedItemId);
} 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. */
private void runExample(
GoogleAdsClient googleAdsClient, Long customerId, Long extensionFeedItemId) {
try (GoogleAdsServiceClient client =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
String extensionFeedItemResourceName =
ResourceNames.extensionFeedItem(customerId, extensionFeedItemId);
ExtensionFeedItem extensionFeedItem =
getExtensionFeedItem(client, customerId, extensionFeedItemId);
// Gets all campaign IDs associated with the extension feed item.
List<Long> campaignIds =
getTargetedCampaignIds(client, customerId, extensionFeedItemResourceName);
// Gets all ad group IDs associated with the extension feed item.
List<Long> adGroupIds =
getTargetedAdGroupIds(client, customerId, extensionFeedItemResourceName);
// Creates a new Promotion asset that matches the target extension feed item.
String promotionAssetResourceName =
createPromotionAssetFromFeed(googleAdsClient, customerId, extensionFeedItem);
// Associates the new Promotion asset with the same campaigns as the original.
associateAssetWithCampaigns(
googleAdsClient, customerId, promotionAssetResourceName, campaignIds);
// Associates the new Promotion asset with the same ad groups as the original.
associateAssetWithAdGroups(
googleAdsClient, customerId, promotionAssetResourceName, adGroupIds);
}
}
/**
* Gets the requested Promotion-type extension feed item.
*
* <p>Note that extensions can also be created via Feed, FeedItem, etc. If you have this type of
* extensions you will need to alter the queries and return types to match your feed type. To do
* so you will need to read the Feed Item via the Feed Mapping and create an asset from the
* contents.
*/
private ExtensionFeedItem getExtensionFeedItem(
GoogleAdsServiceClient client, Long customerId, Long extensionFeedItemId) {
// Creates a query that will retrieve the requested Promotion-type extension feed item and
// ensures that all fields are populated.
String extensionFeedItemQuery =
"SELECT"
+ " extension_feed_item.id,"
+ " extension_feed_item.ad_schedules,"
+ " extension_feed_item.device,"
+ " extension_feed_item.status,"
+ " extension_feed_item.start_date_time,"
+ " extension_feed_item.end_date_time,"
+ " extension_feed_item.targeted_campaign,"
+ " extension_feed_item.targeted_ad_group,"
+ " extension_feed_item.promotion_feed_item.discount_modifier,"
+ " extension_feed_item.promotion_feed_item.final_mobile_urls,"
+ " extension_feed_item.promotion_feed_item.final_url_suffix,"
+ " extension_feed_item.promotion_feed_item.final_urls,"
+ " extension_feed_item.promotion_feed_item.language_code,"
+ " extension_feed_item.promotion_feed_item.money_amount_off.amount_micros,"
+ " extension_feed_item.promotion_feed_item.money_amount_off.currency_code,"
+ " extension_feed_item.promotion_feed_item.occasion,"
+ " extension_feed_item.promotion_feed_item.orders_over_amount.amount_micros,"
+ " extension_feed_item.promotion_feed_item.orders_over_amount.currency_code,"
+ " extension_feed_item.promotion_feed_item.percent_off,"
+ " extension_feed_item.promotion_feed_item.promotion_code,"
+ " extension_feed_item.promotion_feed_item.promotion_end_date,"
+ " extension_feed_item.promotion_feed_item.promotion_start_date,"
+ " extension_feed_item.promotion_feed_item.promotion_target,"
+ " extension_feed_item.promotion_feed_item.tracking_url_template "
+ "FROM extension_feed_item "
+ "WHERE "
+ " extension_feed_item.extension_type = 'PROMOTION' "
+ " AND extension_feed_item.id = "
+ extensionFeedItemId
+ " LIMIT 1";
ServerStream<SearchGoogleAdsStreamResponse> serverStream =
client
.searchStreamCallable()
.call(
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(String.valueOf(customerId))
.setQuery(extensionFeedItemQuery)
.build());
Optional<ExtensionFeedItem> extensionFeedItemResult =
StreamSupport.stream(serverStream.spliterator(), false)
.flatMap(r -> r.getResultsList().stream())
.map(r -> r.getExtensionFeedItem())
.findFirst();
if (!extensionFeedItemResult.isPresent()) {
throw new RuntimeException(
"Unable to find extension feed item in customer ID "
+ customerId
+ " with ID "
+ extensionFeedItemId);
}
ExtensionFeedItem extensionFeedItem = extensionFeedItemResult.get();
System.out.println("Retrieved details for ad extension with ID " + extensionFeedItemId);
// Creates a query to retrieve any URL customer parameters attached to the feed item.
String urlParametersQuery =
"SELECT feed_item.url_custom_parameters "
+ "FROM feed_item "
+ "WHERE feed_item.id = "
+ extensionFeedItemId;
// Issues a search request to get any URL custom parameters.
serverStream =
client
.searchStreamCallable()
.call(
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(String.valueOf(customerId))
.setQuery(urlParametersQuery)
.build());
Optional<FeedItem> urlCustomParametersResult =
StreamSupport.stream(serverStream.spliterator(), false)
.flatMap(r -> r.getResultsList().stream())
.map(r -> r.getFeedItem())
.findFirst();
// Checks for URL custom parameters and adds to the extension feed item if present.
if (urlCustomParametersResult.isPresent()) {
FeedItem feedItem = urlCustomParametersResult.get();
// Converts the ExtensionFeedItem to a builder and populates the URL custom parameters.
ExtensionFeedItem.Builder builder = extensionFeedItem.toBuilder();
builder
.getPromotionFeedItemBuilder()
.addAllUrlCustomParameters(feedItem.getUrlCustomParametersList());
extensionFeedItem = builder.build();
System.out.println(
"Retrieved "
+ feedItem.getUrlCustomParametersCount()
+ " attached URL custom parameters.");
}
return extensionFeedItem;
}
/**
* Finds and returns all of the campaigns that are associated with the specified Promotion
* extension feed item.
*/
private List<Long> getTargetedCampaignIds(
GoogleAdsServiceClient client, Long customerId, String extensionFeedItemResourceName) {
String query =
"SELECT campaign.id, campaign_extension_setting.extension_feed_items "
+ "FROM campaign_extension_setting "
+ "WHERE campaign_extension_setting.extension_type = 'PROMOTION' "
+ " AND campaign.status != 'REMOVED'";
ServerStream<SearchGoogleAdsStreamResponse> serverStream =
client
.searchStreamCallable()
.call(
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(String.valueOf(customerId))
.setQuery(query)
.build());
List<Long> campaignIds = new ArrayList<>();
for (SearchGoogleAdsStreamResponse response : serverStream) {
for (GoogleAdsRow row : response.getResultsList()) {
Campaign campaign = row.getCampaign();
CampaignExtensionSetting extensionSetting = row.getCampaignExtensionSetting();
// Adds the campaign ID to the list of IDs if the extension feed item is
// associated with this extension setting.
if (extensionSetting.getExtensionFeedItemsList().contains(extensionFeedItemResourceName)) {
campaignIds.add(campaign.getId());
System.out.println("Found matching campaign with ID " + campaign.getId());
}
}
}
return campaignIds;
}
/**
* Finds and returns all of the ad groups that are associated with the specified Promotion
* extension feed item.
*/
private List<Long> getTargetedAdGroupIds(
GoogleAdsServiceClient client, Long customerId, String extensionFeedItemResourceName) {
String query =
"SELECT ad_group.id, ad_group_extension_setting.extension_feed_items "
+ "FROM ad_group_extension_setting "
+ "WHERE ad_group_extension_setting.extension_type = 'PROMOTION' "
+ " AND ad_group.status != 'REMOVED'";
ServerStream<SearchGoogleAdsStreamResponse> serverStream =
client
.searchStreamCallable()
.call(
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(String.valueOf(customerId))
.setQuery(query)
.build());
List<Long> adGroupIds = new ArrayList<>();
for (SearchGoogleAdsStreamResponse response : serverStream) {
for (GoogleAdsRow row : response.getResultsList()) {
AdGroup adGroup = row.getAdGroup();
AdGroupExtensionSetting extensionSetting = row.getAdGroupExtensionSetting();
// Adds the ad group ID to the list of IDs if the extension feed item is
// associated with this extension setting.
if (extensionSetting.getExtensionFeedItemsList().contains(extensionFeedItemResourceName)) {
adGroupIds.add(adGroup.getId());
System.out.println("Found matching ad group with ID " + adGroup.getId());
}
}
}
return adGroupIds;
}
/** Creates a Promotion asset that copies values from the specified extension feed item. */
private String createPromotionAssetFromFeed(
GoogleAdsClient googleAdsClient, Long customerId, ExtensionFeedItem extensionFeedItem) {
PromotionFeedItem promotionFeedItem = extensionFeedItem.getPromotionFeedItem();
// Creates the Promotion asset.
Asset.Builder asset =
Asset.newBuilder()
.setName("Migrated from feed item " + extensionFeedItem.getId())
.setTrackingUrlTemplate(promotionFeedItem.getTrackingUrlTemplate())
.setFinalUrlSuffix(promotionFeedItem.getFinalUrlSuffix())
.setPromotionAsset(
PromotionAsset.newBuilder()
.setPromotionTarget(promotionFeedItem.getPromotionTarget())
.setDiscountModifier(promotionFeedItem.getDiscountModifier())
.setRedemptionEndDate(promotionFeedItem.getPromotionStartDate())
.setRedemptionEndDate(promotionFeedItem.getPromotionEndDate())
.setOccasion(promotionFeedItem.getOccasion())
.setLanguageCode(promotionFeedItem.getLanguageCode())
.addAllAdScheduleTargets(extensionFeedItem.getAdSchedulesList()))
.addAllFinalUrls(promotionFeedItem.getFinalUrlsList())
.addAllFinalMobileUrls(promotionFeedItem.getFinalMobileUrlsList())
.addAllUrlCustomParameters(promotionFeedItem.getUrlCustomParametersList());
// Either PercentOff or MoneyAmountOff must be set.
if (promotionFeedItem.getPercentOff() > 0) {
// Adjusts the percent off scale when copying.
asset.getPromotionAssetBuilder().setPercentOff(promotionFeedItem.getPercentOff() / 100);
} else {
asset.getPromotionAssetBuilder().setMoneyAmountOff(promotionFeedItem.getMoneyAmountOff());
}
// Either PromotionCode or OrdersOverAmount must be set.
if (promotionFeedItem.getPromotionCode() != null
&& promotionFeedItem.getPromotionCode().length() > 0) {
asset.getPromotionAssetBuilder().setPromotionCode(promotionFeedItem.getPromotionCode());
} else {
asset.getPromotionAssetBuilder().setOrdersOverAmount(promotionFeedItem.getOrdersOverAmount());
}
// Sets the start and end dates if set in the existing extension.
if (extensionFeedItem.hasStartDateTime()) {
asset.getPromotionAssetBuilder().setStartDate(extensionFeedItem.getStartDateTime());
}
if (extensionFeedItem.hasEndDateTime()) {
asset.getPromotionAssetBuilder().setEndDate(extensionFeedItem.getEndDateTime());
}
// Builds an operation to create the Promotion asset.
AssetOperation operation = AssetOperation.newBuilder().setCreate(asset).build();
// Gets the Asset Service client.
try (AssetServiceClient assetServiceClient =
googleAdsClient.getLatestVersion().createAssetServiceClient()) {
// Issues the request and returns the resource name of the new Promotion asset.
MutateAssetsResponse response =
assetServiceClient.mutateAssets(String.valueOf(customerId), ImmutableList.of(operation));
String resourceName = response.getResults(0).getResourceName();
System.out.println("Created Promotion asset with resource name " + resourceName);
return resourceName;
}
}
/** Associates the specified Promotion asset with the specified campaigns. */
private void associateAssetWithCampaigns(
GoogleAdsClient googleAdsClient,
Long customerId,
String promotionAssetResourceName,
List<Long> campaignIds) {
if (campaignIds.isEmpty()) {
System.out.println("Asset was not associated with any campaigns.");
return;
}
// Constructs an operation to associate the asset with each campaign.
List<CampaignAssetOperation> campaignAssetOperations =
campaignIds.stream()
.map(
id ->
CampaignAssetOperation.newBuilder()
.setCreate(
CampaignAsset.newBuilder()
.setAsset(promotionAssetResourceName)
.setFieldType(AssetFieldType.PROMOTION)
.setCampaign(ResourceNames.campaign(customerId, id)))
.build())
.collect(Collectors.toList());
// Creates a service client.
try (CampaignAssetServiceClient campaignAssetServiceClient =
googleAdsClient.getLatestVersion().createCampaignAssetServiceClient()) {
// Issues the mutate request.
MutateCampaignAssetsResponse response =
campaignAssetServiceClient.mutateCampaignAssets(
String.valueOf(customerId), campaignAssetOperations);
// Prints some information about the result.
for (MutateCampaignAssetResult result : response.getResultsList()) {
System.out.println("Created campaign asset with resource name " + result.getResourceName());
}
}
}
/** Associates the specified Promotion asset with the specified ad groups. */
private void associateAssetWithAdGroups(
GoogleAdsClient googleAdsClient,
Long customerId,
String promotionAssetResourceName,
List<Long> adGroupIds) {
if (adGroupIds.isEmpty()) {
System.out.println("Asset was not associated with any ad groups.");
return;
}
// Creates an operation to associate the asset with each ad group.
List<AdGroupAssetOperation> adGroupAssetOperations =
adGroupIds.stream()
.map(
id ->
AdGroupAssetOperation.newBuilder()
.setCreate(
AdGroupAsset.newBuilder()
.setAsset(promotionAssetResourceName)
.setFieldType(AssetFieldType.PROMOTION)
.setAdGroup(ResourceNames.adGroup(customerId, id)))
.build())
.collect(Collectors.toList());
// Creates a service client.
try (AdGroupAssetServiceClient adGroupAssetServiceClient =
googleAdsClient.getLatestVersion().createAdGroupAssetServiceClient()) {
// Issues the mutate request.
MutateAdGroupAssetsResponse response =
adGroupAssetServiceClient.mutateAdGroupAssets(
String.valueOf(customerId), adGroupAssetOperations);
// Prints some information about the result.
for (MutateAdGroupAssetResult result : response.getResultsList()) {
System.out.println("Created campaign asset with resource name " + result.getResourceName());
}
}
}
}
С#
// Copyright 2021 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.V13.Common;
using Google.Ads.GoogleAds.V13.Enums;
using Google.Ads.GoogleAds.V13.Errors;
using Google.Ads.GoogleAds.V13.Resources;
using Google.Ads.GoogleAds.V13.Services;
using Google.Protobuf.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Google.Ads.GoogleAds.Examples.V13
{
/// <summary>
/// This code example retrieves the full details of a Promotion Feed-based extension and
/// creates a matching Promotion asset-based extension. The new Asset-based extension will
/// then be associated with the same campaigns and ad groups as the original Feed-based
/// extension.
/// Once copied, you should remove the Feed-based extension; see
/// RemoveEntireSitelinkCampaignExtensionSetting.cs for an example.
/// </summary>
public class MigratePromotionFeedToAsset : ExampleBase
{
/// <summary>
/// Command line options for running the <see cref="MigratePromotionFeedToAsset"/> 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>
/// ID of the extension feed item to migrate.
/// </summary>
[Option("feedItemId", Required = true, HelpText =
"ID of the extension feed item to migrate.")]
public long FeedItemId { 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);
MigratePromotionFeedToAsset codeExample = new MigratePromotionFeedToAsset();
Console.WriteLine(codeExample.Description);
codeExample.Run(new GoogleAdsClient(), options.CustomerId, options.FeedItemId);
}
/// <summary>
/// Returns a description about the code example.
/// </summary>
public override string Description =>
"This code example retrieves the full details of a Promotion Feed-based extension " +
"and creates a matching Promotion asset-based extension. The new Asset-based " +
"extension will then be associated with the same campaigns and ad groups as the " +
"original Feed-based extension.\n" +
"Once copied, you should remove the Feed-based extension; see " +
"RemoveEntireSitelinkCampaignExtensionSetting.cs for an example.";
/// <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="feedItemId">ID of the extension feed item to migrate.</param>
public void Run(GoogleAdsClient client, long customerId, long feedItemId)
{
// Get the GoogleAdsService client.
GoogleAdsServiceClient googleAdsServiceClient =
client.GetService(Services.V13.GoogleAdsService);
string extensionFeedItemResourceName =
ResourceNames.ExtensionFeedItem(customerId, feedItemId);
try
{
// Get the target extension feed item.
ExtensionFeedItem extensionFeedItem =
GetExtensionFeedItem(googleAdsServiceClient, customerId, feedItemId);
// Get all campaign IDs associated with the extension feed item.
List<long> campaignIds = GetTargetedCampaignIds(googleAdsServiceClient, customerId,
extensionFeedItemResourceName);
// Get all ad group IDs associated with the extension feed item.
List<long> adGroupIds = GetTargetedAdGroupIds(googleAdsServiceClient, customerId,
extensionFeedItemResourceName);
// Create a new Promotion asset that matches the target extension feed item.
string promotionAssetResourceName = CreatePromotionAssetFromFeed(client,
customerId, extensionFeedItem);
// Associate the new Promotion asset with the same campaigns as the original.
AssociateAssetWithCampaigns(client, customerId, promotionAssetResourceName,
campaignIds);
// Associate the new Promotion asset with the same ad groups as the original.
AssociateAssetWithAdGroups(client, customerId, promotionAssetResourceName,
adGroupIds);
}
catch (GoogleAdsException e)
{
Console.WriteLine("Failure:");
Console.WriteLine($"Message: {e.Message}");
Console.WriteLine($"Failure: {e.Failure}");
Console.WriteLine($"Request ID: {e.RequestId}");
throw;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
throw;
}
}
/// <summary>
/// Gets the requested Promotion-type extension feed item.
///
/// Note that extension feed items pertain to feeds that were created by Google. Use
/// FeedService to instead retrieve a user-created Feed.
/// </summary>
/// <param name="googleAdsServiceClient">An initialized Google Ads API Service
/// client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="feedItemId">ID of the extension feed item to migrate.</param>
/// <returns>The requested ExtensionFeedItem, or null if no matching item was
/// found.</returns>
private ExtensionFeedItem GetExtensionFeedItem(
GoogleAdsServiceClient googleAdsServiceClient,
long customerId, long feedItemId)
{
// Create a query that will retrieve the requested Promotion-type extension feed item
// and ensure that all fields are populated.
string extensionFeedItemQuery = $@"
SELECT
extension_feed_item.id,
extension_feed_item.ad_schedules,
extension_feed_item.device,
extension_feed_item.status,
extension_feed_item.start_date_time,
extension_feed_item.end_date_time,
extension_feed_item.targeted_campaign,
extension_feed_item.targeted_ad_group,
extension_feed_item.promotion_feed_item.discount_modifier,
extension_feed_item.promotion_feed_item.final_mobile_urls,
extension_feed_item.promotion_feed_item.final_url_suffix,
extension_feed_item.promotion_feed_item.final_urls,
extension_feed_item.promotion_feed_item.language_code,
extension_feed_item.promotion_feed_item.money_amount_off.amount_micros,
extension_feed_item.promotion_feed_item.money_amount_off.currency_code,
extension_feed_item.promotion_feed_item.occasion,
extension_feed_item.promotion_feed_item.orders_over_amount.amount_micros,
extension_feed_item.promotion_feed_item.orders_over_amount.currency_code,
extension_feed_item.promotion_feed_item.percent_off,
extension_feed_item.promotion_feed_item.promotion_code,
extension_feed_item.promotion_feed_item.promotion_end_date,
extension_feed_item.promotion_feed_item.promotion_start_date,
extension_feed_item.promotion_feed_item.promotion_target,
extension_feed_item.promotion_feed_item.tracking_url_template
FROM extension_feed_item
WHERE
extension_feed_item.extension_type = 'PROMOTION'
AND extension_feed_item.id = {feedItemId}
LIMIT 1";
ExtensionFeedItem fetchedExtensionFeedItem = null;
// Issue a search request to get the extension feed item contents.
googleAdsServiceClient.SearchStream(customerId.ToString(), extensionFeedItemQuery,
delegate (SearchGoogleAdsStreamResponse response)
{
fetchedExtensionFeedItem = response.Results.First().ExtensionFeedItem;
}
);
Console.WriteLine(
$"Retrieved details for ad extension with ID {fetchedExtensionFeedItem.Id}.");
// Create a query to retrieve any URL customer parameters attached to the feed item.
string urlCustomParametersQuery = $@"
SELECT feed_item.url_custom_parameters
FROM feed_item
WHERE feed_item.id = {feedItemId}";
// Issue a search request to get any URL custom parameters.
googleAdsServiceClient.SearchStream(customerId.ToString(), urlCustomParametersQuery,
delegate (SearchGoogleAdsStreamResponse response)
{
RepeatedField<CustomParameter> urlCustomParameters =
response.Results.First().FeedItem.UrlCustomParameters;
Console.WriteLine(
$"Retrieved {urlCustomParameters.Count} attached URL custom parameters.");
if (urlCustomParameters.Count > 0)
{
fetchedExtensionFeedItem.PromotionFeedItem.UrlCustomParameters.Add(
urlCustomParameters);
}
}
);
return fetchedExtensionFeedItem;
}
/// <summary>
/// Finds and returns all of the campaigns that are associated with the specified Promotion
/// extension feed item.
/// </summary>
/// <param name="googleAdsServiceClient">An initialized Google Ads API Service
/// client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="extensionFeedResourceName">ID of the extension feed item to
/// migrate.</param>
/// <returns>A list of campaign IDs.</returns>
private List<long> GetTargetedCampaignIds(GoogleAdsServiceClient googleAdsServiceClient,
long customerId, string extensionFeedResourceName)
{
List<long> campaignIds = new List<long>();
string query = @"
SELECT campaign.id, campaign_extension_setting.extension_feed_items
FROM campaign_extension_setting
WHERE campaign_extension_setting.extension_type = 'PROMOTION'
AND campaign.status != 'REMOVED'";
googleAdsServiceClient.SearchStream(customerId.ToString(), query,
delegate (SearchGoogleAdsStreamResponse response)
{
foreach (GoogleAdsRow googleAdsRow in response.Results)
{
// Add the campaign ID to the list of IDs if the extension feed item is
// associated with this extension setting.
if (googleAdsRow.CampaignExtensionSetting.ExtensionFeedItems.Contains(
extensionFeedResourceName))
{
Console.WriteLine(
$"Found matching campaign with ID {googleAdsRow.Campaign.Id}.");
campaignIds.Add(googleAdsRow.Campaign.Id);
}
}
}
);
return campaignIds;
}
/// <summary>
/// Finds and returns all of the ad groups that are associated with the specified Promotion
/// extension feed item.
/// </summary>
/// <param name="googleAdsServiceClient">An initialized Google Ads API Service
/// client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="extensionFeedItemResourceName">Resource name of the extension feed item to
/// migrate.</param>
/// <returns>A list of ad group IDs.</returns>
private List<long> GetTargetedAdGroupIds(
GoogleAdsServiceClient googleAdsServiceClient, long customerId,
string extensionFeedItemResourceName)
{
List<long> adGroupIds = new List<long>();
string query = @"
SELECT ad_group.id, ad_group_extension_setting.extension_feed_items
FROM ad_group_extension_setting
WHERE ad_group_extension_setting.extension_type = 'PROMOTION'
AND ad_group.status != 'REMOVED'";
googleAdsServiceClient.SearchStream(customerId.ToString(), query,
delegate (SearchGoogleAdsStreamResponse response)
{
foreach (GoogleAdsRow googleAdsRow in response.Results)
{
// Add the ad group ID to the list of IDs if the extension feed item is
// associated with this extension setting.
if (googleAdsRow.AdGroupExtensionSetting.ExtensionFeedItems.Contains(
extensionFeedItemResourceName))
{
Console.WriteLine(
$"Found matching ad group with ID {googleAdsRow.AdGroup.Id}.");
adGroupIds.Add(googleAdsRow.AdGroup.Id);
}
}
}
);
return adGroupIds;
}
/// <summary>
/// Create a Promotion asset that copies values from the specified extension feed item.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="extensionFeedItem">The extension feed item to be migrated.</param>
/// <returns>The resource name of the newly created Promotion asset.</returns>
private string CreatePromotionAssetFromFeed(GoogleAdsClient client, long customerId,
ExtensionFeedItem extensionFeedItem)
{
// Get the Asset Service client.
AssetServiceClient assetServiceClient = client.GetService(Services.V13.AssetService);
PromotionFeedItem promotionFeedItem = extensionFeedItem.PromotionFeedItem;
// Create the Promotion asset.
Asset asset = new Asset
{
// Name field is optional.
Name = $"Migrated from feed item #{extensionFeedItem.Id}",
PromotionAsset = new PromotionAsset
{
PromotionTarget = promotionFeedItem.PromotionTarget,
DiscountModifier = promotionFeedItem.DiscountModifier,
RedemptionStartDate = promotionFeedItem.PromotionStartDate,
RedemptionEndDate = promotionFeedItem.PromotionEndDate,
Occasion = promotionFeedItem.Occasion,
LanguageCode = promotionFeedItem.LanguageCode,
},
TrackingUrlTemplate = promotionFeedItem.TrackingUrlTemplate,
FinalUrlSuffix = promotionFeedItem.FinalUrlSuffix
};
// Either PercentOff or MoneyAmountOff must be set.
if (promotionFeedItem.PercentOff > 0)
{
// Adjust the percent off scale when copying.
asset.PromotionAsset.PercentOff = promotionFeedItem.PercentOff / 100;
}
else
{
asset.PromotionAsset.MoneyAmountOff = new Money
{
AmountMicros = promotionFeedItem.MoneyAmountOff.AmountMicros,
CurrencyCode = promotionFeedItem.MoneyAmountOff.CurrencyCode
};
}
// Either PromotionCode or OrdersOverAmount must be set.
if (!string.IsNullOrEmpty(promotionFeedItem.PromotionCode))
{
asset.PromotionAsset.PromotionCode = promotionFeedItem.PromotionCode;
}
else
{
asset.PromotionAsset.OrdersOverAmount = new Money
{
AmountMicros = promotionFeedItem.OrdersOverAmount.AmountMicros,
CurrencyCode = promotionFeedItem.OrdersOverAmount.CurrencyCode
};
}
// Set the start and end dates if set in the existing extension.
if (extensionFeedItem.HasStartDateTime)
{
asset.PromotionAsset.StartDate = DateTime.Parse(extensionFeedItem.StartDateTime)
.ToString("yyyy-MM-dd");
}
if (extensionFeedItem.HasEndDateTime)
{
asset.PromotionAsset.EndDate = DateTime.Parse(extensionFeedItem.EndDateTime)
.ToString("yyyy-MM-dd");
}
asset.PromotionAsset.AdScheduleTargets.Add(extensionFeedItem.AdSchedules);
asset.FinalUrls.Add(promotionFeedItem.FinalUrls);
asset.FinalMobileUrls.Add(promotionFeedItem.FinalMobileUrls);
asset.UrlCustomParameters.Add(promotionFeedItem.UrlCustomParameters);
// Build an operation to create the Promotion asset.
AssetOperation operation = new AssetOperation
{
Create = asset
};
// Issue the request and return the resource name of the new Promotion asset.
MutateAssetsResponse response = assetServiceClient.MutateAssets(
customerId.ToString(), new[] { operation });
Console.WriteLine("Created Promotion asset with resource name " +
$"{response.Results.First().ResourceName}");
return response.Results.First().ResourceName;
}
/// <summary>
/// Associates the specified Promotion asset with the specified campaigns.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="promotionAssetResourceName">The string resource name of the Promotion
/// Asset.</param>
/// <param name="campaignIds">A list of campaign IDs with which the Asset should be
/// associated.</param>
private void AssociateAssetWithCampaigns(GoogleAdsClient client, long customerId,
string promotionAssetResourceName, List<long> campaignIds)
{
if (campaignIds.Count == 0)
{
Console.WriteLine("Asset was not associated with any campaigns.");
return;
}
CampaignAssetServiceClient campaignAssetServiceClient = client.GetService(Services.V13
.CampaignAssetService);
List<CampaignAssetOperation> operations = new List<CampaignAssetOperation>();
foreach (long campaignId in campaignIds)
{
operations.Add(new CampaignAssetOperation
{
Create = new CampaignAsset
{
Asset = promotionAssetResourceName,
FieldType = AssetFieldTypeEnum.Types.AssetFieldType.Promotion,
Campaign = ResourceNames.Campaign(customerId, campaignId),
}
});
}
MutateCampaignAssetsResponse response = campaignAssetServiceClient.MutateCampaignAssets(
customerId.ToString(), operations);
foreach (MutateCampaignAssetResult result in response.Results)
{
Console.WriteLine($"Created campaign asset with resource name " +
$"{result.ResourceName}.");
}
}
/// <summary>
/// Associates the specified Promotion asset with the specified ad groups.
/// </summary>
/// <param name="client">The Google Ads client.</param>
/// <param name="customerId">The customer ID for which the call is made.</param>
/// <param name="promotionAssetResourceName">The string resource name of the Promotion
/// Asset.</param>
/// <param name="adGroupIds">A list of ad group IDs with which the Asset should be
/// associated.</param>
private void AssociateAssetWithAdGroups(GoogleAdsClient client, long customerId,
string promotionAssetResourceName, List<long> adGroupIds)
{
if (adGroupIds.Count == 0)
{
Console.WriteLine("Asset was not associated with any ad groups.");
return;
}
AdGroupAssetServiceClient adGroupAssetServiceClient = client.GetService(Services.V13
.AdGroupAssetService);
List<AdGroupAssetOperation> operations = new List<AdGroupAssetOperation>();
foreach (long adGroupId in adGroupIds)
{
operations.Add(new AdGroupAssetOperation
{
Create = new AdGroupAsset
{
Asset = promotionAssetResourceName,
FieldType = AssetFieldTypeEnum.Types.AssetFieldType.Promotion,
AdGroup = ResourceNames.AdGroup(customerId, adGroupId),
}
});
}
MutateAdGroupAssetsResponse response = adGroupAssetServiceClient.MutateAdGroupAssets(
customerId.ToString(), operations);
foreach (MutateAdGroupAssetResult result in response.Results)
{
Console.WriteLine($"Created ad group asset with resource name " +
$"{result.ResourceName}.");
}
}
}
}
PHP
<?php
/**
* Copyright 2021 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\Lib\OAuth2TokenBuilder;
use Google\Ads\GoogleAds\Lib\V13\GoogleAdsClient;
use Google\Ads\GoogleAds\Lib\V13\GoogleAdsClientBuilder;
use Google\Ads\GoogleAds\Lib\V13\GoogleAdsException;
use Google\Ads\GoogleAds\Lib\V13\GoogleAdsServerStreamDecorator;
use Google\Ads\GoogleAds\Util\V13\ResourceNames;
use Google\Ads\GoogleAds\V13\Common\Money;
use Google\Ads\GoogleAds\V13\Common\PromotionAsset;
use Google\Ads\GoogleAds\V13\Enums\AssetFieldTypeEnum\AssetFieldType;
use Google\Ads\GoogleAds\V13\Errors\GoogleAdsError;
use Google\Ads\GoogleAds\V13\Resources\AdGroupAsset;
use Google\Ads\GoogleAds\V13\Resources\Asset;
use Google\Ads\GoogleAds\V13\Resources\CampaignAsset;
use Google\Ads\GoogleAds\V13\Resources\ExtensionFeedItem;
use Google\Ads\GoogleAds\V13\Resources\FeedItem;
use Google\Ads\GoogleAds\V13\Services\AdGroupAssetOperation;
use Google\Ads\GoogleAds\V13\Services\AssetOperation;
use Google\Ads\GoogleAds\V13\Services\CampaignAssetOperation;
use Google\Ads\GoogleAds\V13\Services\GoogleAdsRow;
use Google\ApiCore\ApiException;
/**
* This code example retrieves the full details of a Promotion Feed-based extension and
* creates a matching Promotion asset-based extension. The new Asset-based extension will
* then be associated with the same campaigns and ad groups as the original Feed-based
* extension.
* Once copied, you should remove the Feed-based extension; see
* RemoveEntireSitelinkCampaignExtensionSetting.php for an example.
*/
class MigratePromotionFeedToAsset
{
private const CUSTOMER_ID = 'INSERT_CUSTOMER_ID_HERE';
// The ID of the extension feed item to migrate.
private const FEED_ITEM_ID = 'INSERT_FEED_ITEM_ID_HERE';
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::FEED_ITEM_ID => 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::FEED_ITEM_ID] ?: self::FEED_ITEM_ID
);
} 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 int $feedItemId ID of the extension feed item to migrate
*/
public static function runExample(
GoogleAdsClient $googleAdsClient,
int $customerId,
int $feedItemId
) {
$extensionFeedItemResourceName =
ResourceNames::forExtensionFeedItem($customerId, $feedItemId);
// Get the target extension feed item.
$extensionFeedItem = self::getExtensionFeedItem($googleAdsClient, $customerId, $feedItemId);
// Get all campaign IDs associated with the extension feed item.
$campaignIds = self::getTargetedCampaignIds(
$googleAdsClient,
$customerId,
$extensionFeedItemResourceName
);
// Get all ad group IDs associated with the extension feed item.
$adGroupIds = self::getTargetedAdGroupIds(
$googleAdsClient,
$customerId,
$extensionFeedItemResourceName
);
// Create a new Promotion asset that matches the target extension feed item.
$promotionAssetResourceName =
self::createPromotionAssetFromFeed($googleAdsClient, $customerId, $extensionFeedItem);
// Associate the new Promotion asset with the same campaigns as the original.
self::associateAssetWithCampaigns(
$googleAdsClient,
$customerId,
$promotionAssetResourceName,
$campaignIds
);
// Associate the new Promotion asset with the same ad groups as the original.
self::associateAssetWithAdGroups(
$googleAdsClient,
$customerId,
$promotionAssetResourceName,
$adGroupIds
);
}
/**
* Gets the requested Promotion-type extension feed item.
*
* Note that extension feed items pertain to feeds that were created by Google. Use
* FeedService to instead retrieve a user-created Feed.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the client customer ID
* @param int $feedItemId the ID of the extension feed item to fetch
* @return ExtensionFeedItem|null the requested extension feed item or null if no matching
* extension feed item was found
*/
private static function getExtensionFeedItem(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $feedItemId
): ?ExtensionFeedItem {
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
// Create a query that will retrieve the requested Promotion-type extension feed item
// and ensure that all fields are populated.
$query = "SELECT
extension_feed_item.id,
extension_feed_item.ad_schedules,
extension_feed_item.device,
extension_feed_item.status,
extension_feed_item.start_date_time,
extension_feed_item.end_date_time,
extension_feed_item.targeted_campaign,
extension_feed_item.targeted_ad_group,
extension_feed_item.promotion_feed_item.discount_modifier,
extension_feed_item.promotion_feed_item.final_mobile_urls,
extension_feed_item.promotion_feed_item.final_url_suffix,
extension_feed_item.promotion_feed_item.final_urls,
extension_feed_item.promotion_feed_item.language_code,
extension_feed_item.promotion_feed_item.money_amount_off.amount_micros,
extension_feed_item.promotion_feed_item.money_amount_off.currency_code,
extension_feed_item.promotion_feed_item.occasion,
extension_feed_item.promotion_feed_item.orders_over_amount.amount_micros,
extension_feed_item.promotion_feed_item.orders_over_amount.currency_code,
extension_feed_item.promotion_feed_item.percent_off,
extension_feed_item.promotion_feed_item.promotion_code,
extension_feed_item.promotion_feed_item.promotion_end_date,
extension_feed_item.promotion_feed_item.promotion_start_date,
extension_feed_item.promotion_feed_item.promotion_target,
extension_feed_item.promotion_feed_item.tracking_url_template
FROM extension_feed_item
WHERE
extension_feed_item.extension_type = 'PROMOTION'
AND extension_feed_item.id = $feedItemId
LIMIT 1";
$fetchedExtensionFeedItem = null;
// Issue a search request to get the extension feed item contents.
/** @var GoogleAdsServerStreamDecorator $stream */
$stream = $googleAdsServiceClient->searchStream($customerId, $query);
$currentElement = $stream->iterateAllElements()->current();
if (!is_null($currentElement)) {
/** @var ExtensionFeedItem $fetchedExtensionFeedItem */
$fetchedExtensionFeedItem = $currentElement->getExtensionFeedItem();
printf(
"Retrieved details for extension feed item with ID %d.%s",
$fetchedExtensionFeedItem->getId(),
PHP_EOL
);
} else {
// No need to get URL custom parameters if the extension feed item wasn't found.
return null;
}
// Create a query to retrieve any URL customer parameters attached to the feed item.
$urlCustomParametersQuery = "SELECT feed_item.url_custom_parameters FROM feed_item "
. "WHERE feed_item.id = $feedItemId";
// Issue a search request to get any URL custom parameters.
/** @var GoogleAdsServerStreamDecorator $stream */
$stream = $googleAdsServiceClient->searchStream($customerId, $urlCustomParametersQuery);
/** @var FeedItem $fetchedFeedItem */
$fetchedFeedItem = $stream->iterateAllElements()->current()->getFeedItem();
$urlCustomParameters = $fetchedFeedItem->getUrlCustomParameters();
printf(
"Retrieved %d attached URL custom parameters.%s",
count($urlCustomParameters),
PHP_EOL
);
if (!empty($urlCustomParameters)) {
$fetchedExtensionFeedItem->getPromotionFeedItem()->setUrlCustomParameters(
$urlCustomParameters
);
}
return $fetchedExtensionFeedItem;
}
/**
* Finds and returns all of the campaigns that are associated with the specified Promotion
* extension feed item.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the client customer ID
* @param int $extensionFeedItemResourceName the resource name of the extension feed item to
* migrate
* @return int[] the list of campaign IDs associated with the specified extension feed item
*/
private static function getTargetedCampaignIds(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $extensionFeedItemResourceName
): array {
$campaignIds = [];
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
// Create a query that will retrieve the campaign extension settings.
$query = "SELECT campaign.id, campaign_extension_setting.extension_feed_items "
. "FROM campaign_extension_setting "
. "WHERE campaign_extension_setting.extension_type = 'PROMOTION' "
. "AND campaign.status != 'REMOVED'";
// Issue a search request to get the campaign extension settings.
/** @var GoogleAdsServerStreamDecorator $stream */
$stream = $googleAdsServiceClient->searchStream($customerId, $query);
foreach ($stream->iterateAllElements() as $googleAdsRow) {
/** @var GoogleAdsRow $googleAdsRow */
// Add the campaign ID to the list of IDs if the extension feed item is
// associated with this extension setting.
if (
in_array(
$extensionFeedItemResourceName,
iterator_to_array(
$googleAdsRow->getCampaignExtensionSetting()->getExtensionFeedItems()
)
)
) {
printf(
"Found matching campaign with ID %d.%s",
$googleAdsRow->getCampaign()->getId(),
PHP_EOL
);
$campaignIds[] = $googleAdsRow->getCampaign()->getId();
}
}
return $campaignIds;
}
/**
* Finds and returns all of the ad groups that are associated with the specified Promotion
* extension feed item.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the client customer ID
* @param int $extensionFeedItemResourceName the resource name of the extension feed item to
* migrate
* @return int[] the list of ad group IDs associated with the specified extension feed item
*/
private static function getTargetedAdGroupIds(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $extensionFeedItemResourceName
): array {
$adGroupIds = [];
$googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient();
// Create a query that will retrieve the ad group extension settings.
$query = "SELECT ad_group.id, ad_group_extension_setting.extension_feed_items "
. "FROM ad_group_extension_setting "
. "WHERE ad_group_extension_setting.extension_type = 'PROMOTION' "
. "AND ad_group.status != 'REMOVED'";
// Issue a search request to get the ad group extension settings.
/** @var GoogleAdsServerStreamDecorator $stream */
$stream = $googleAdsServiceClient->searchStream($customerId, $query);
foreach ($stream->iterateAllElements() as $googleAdsRow) {
/** @var GoogleAdsRow $googleAdsRow */
// Add the ad group ID to the list of IDs if the extension feed item is
// associated with this extension setting.
if (
in_array(
$extensionFeedItemResourceName,
iterator_to_array(
$googleAdsRow->getAdGroupExtensionSetting()->getExtensionFeedItems()
)
)
) {
printf(
"Found matching ad group with ID %d.%s",
$googleAdsRow->getAdGroup()->getId(),
PHP_EOL
);
$adGroupIds[] = $googleAdsRow->getAdGroup()->getId();
}
}
return $adGroupIds;
}
/**
* Create a Promotion asset that copies values from the specified extension feed item.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param ExtensionFeedItem $extensionFeedItem the extension feed item to be migrated
* @return string the resource name of the newly created Promotion asset
*/
private static function createPromotionAssetFromFeed(
GoogleAdsClient $googleAdsClient,
int $customerId,
ExtensionFeedItem $extensionFeedItem
): string {
$promotionFeedItem = $extensionFeedItem->getPromotionFeedItem();
// Creates the Promotion asset.
$asset = new Asset([
// Name field is optional.
'name' => 'Migrated from feed item #' . $extensionFeedItem->getId(),
'promotion_asset' => new PromotionAsset([
'promotion_target' => $promotionFeedItem->getPromotionTarget(),
'discount_modifier' => $promotionFeedItem->getDiscountModifier(),
'redemption_start_date' => $promotionFeedItem->getPromotionStartDate(),
'redemption_end_date' => $promotionFeedItem->getPromotionEndDate(),
'occasion' => $promotionFeedItem->getOccasion(),
'language_code' => $promotionFeedItem->getLanguageCode(),
'ad_schedule_targets' => $extensionFeedItem->getAdSchedules()
]),
'tracking_url_template' => $promotionFeedItem->getTrackingUrlTemplate(),
'url_custom_parameters' => $promotionFeedItem->getUrlCustomParameters(),
'final_urls' => $promotionFeedItem->getFinalUrls(),
'final_mobile_urls' => $promotionFeedItem->getFinalMobileUrls(),
'final_url_suffix' => $promotionFeedItem->getFinalUrlSuffix(),
]);
// Either percent off or money amount off must be set.
if ($promotionFeedItem->getPercentOff() > 0) {
// Adjust the percent off scale when copying.
$asset->getPromotionAsset()->setPercentOff($promotionFeedItem->getPercentOff() / 100);
} else {
$money = new Money([
'amount_micros' => $promotionFeedItem->getMoneyAmountOff()->getAmountMicros(),
'currency_code' => $promotionFeedItem->getMoneyAmountOff()->getCurrencyCode()
]);
$asset->getPromotionAsset()->setMoneyAmountOff($money);
}
// Either promotion code or orders over amount must be set.
if (!empty($promotionFeedItem->getPromotionCode())) {
$asset->getPromotionAsset()->setPromotionCode($promotionFeedItem->getPromotionCode());
} else {
$money = new Money([
'amount_micros' => $promotionFeedItem->getOrdersOverAmount()->getAmountMicros(),
'currency_code' => $promotionFeedItem->getOrdersOverAmount()->getCurrencyCode()
]);
$asset->getPromotionAsset()->setOrdersOverAmount($money);
}
if ($extensionFeedItem->hasStartDateTime()) {
$startDateTime = new \DateTime($extensionFeedItem->getStartDateTime());
$asset->getPromotionAsset()->setStartDate($startDateTime->format('yyyy-MM-dd'));
}
if ($extensionFeedItem->hasEndDateTime()) {
$endDateTime = new \DateTime($extensionFeedItem->getEndDateTime());
$asset->getPromotionAsset()->setEndDate($endDateTime->format('yyyy-MM-dd'));
}
// Creates an operation to add the Promotion asset.
$assetOperation = new AssetOperation();
$assetOperation->setCreate($asset);
// Issues a mutate request to add the Promotion asset and prints its information.
$assetServiceClient = $googleAdsClient->getAssetServiceClient();
$response = $assetServiceClient->mutateAssets($customerId, [$assetOperation]);
$assetResourceName = $response->getResults()[0]->getResourceName();
printf(
"Created the Promotion asset with resource name: '%s'.%s",
$assetResourceName,
PHP_EOL
);
return $assetResourceName;
}
/**
* Associates the specified Promotion asset with the specified campaigns.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param string $promotionAssetResourceName the resource name of the Promotion asset
* @param int[] $campaignIds the IDs of the campaigns with which assets should be associated
*/
private static function associateAssetWithCampaigns(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $promotionAssetResourceName,
array $campaignIds
) {
if (empty($campaignIds)) {
print 'Asset was not associated with any campaigns.' . PHP_EOL;
return;
}
$operations = [];
foreach ($campaignIds as $campaignId) {
$operations[] = new CampaignAssetOperation([
'create' => new CampaignAsset([
'asset' => $promotionAssetResourceName,
'field_type' => AssetFieldType::PROMOTION,
'campaign' => ResourceNames::forCampaign($customerId, $campaignId)
])
]);
}
// Issues a mutate request to add the campaign assets and prints their information.
$campaignAssetServiceClient = $googleAdsClient->getCampaignAssetServiceClient();
$response = $campaignAssetServiceClient->mutateCampaignAssets($customerId, $operations);
foreach ($response->getResults() as $addedCampaignAsset) {
/** @var CampaignAsset $addedCampaignAsset */
printf(
"Created campaign asset with resource name: '%s'.%s",
$addedCampaignAsset->getResourceName(),
PHP_EOL
);
}
}
/**
* Associates the specified Promotion asset with the specified ad groups.
*
* @param GoogleAdsClient $googleAdsClient the Google Ads API client
* @param int $customerId the customer ID
* @param string $promotionAssetResourceName the resource name of the Promotion asset
* @param int[] $adGroupIds the IDs of the ad groups with which assets should be associated
*/
private static function associateAssetWithAdGroups(
GoogleAdsClient $googleAdsClient,
int $customerId,
string $promotionAssetResourceName,
array $adGroupIds
) {
if (empty($adGroupIds)) {
print 'Asset was not associated with any ad groups.' . PHP_EOL;
return;
}
$operations = [];
foreach ($adGroupIds as $adGroupId) {
$operations[] = new AdGroupAssetOperation([
'create' => new AdGroupAsset([
'asset' => $promotionAssetResourceName,
'field_type' => AssetFieldType::PROMOTION,
'ad_group' => ResourceNames::forAdGroup($customerId, $adGroupId)
])
]);
}
// Issues a mutate request to add the ad group assets and prints their information.
$adGroupAssetServiceClient = $googleAdsClient->getAdGroupAssetServiceClient();
$response = $adGroupAssetServiceClient->mutateAdGroupAssets($customerId, $operations);
foreach ($response->getResults() as $addedAdGroupAsset) {
/** @var AdGroupAsset $addedAdGroupAsset */
printf(
"Created ad group asset with resource name: '%s'.%s",
$addedAdGroupAsset->getResourceName(),
PHP_EOL
);
}
}
}
MigratePromotionFeedToAsset::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.
"""Migrates a feed-based promotion extension to an asset-based extension.
The new asset-based extension will then be associated with the same campaigns
and ad groups as the original feed-based extension. Finally, the old feed-based
extension will be mutated so it no longer serves.
"""
import argparse
import sys
from uuid import uuid4
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
def main(client, customer_id, feed_item_id):
"""The main method that creates all necessary entities for the example.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
feed_item_id: an extension feed item ID.
"""
extension_feed_item_service = client.get_service("ExtensionFeedItemService")
resource_name = extension_feed_item_service.extension_feed_item_path(
customer_id, feed_item_id
)
# Get the target extension feed item
extension_feed_item = get_extension_feed_item(
client, customer_id, feed_item_id
)
# Get all campaign IDs associated with the extension feed item.
campaign_ids = get_targeted_campaign_ids(client, customer_id, resource_name)
# Get all ad group IDs associated with the extension feed item.
ad_group_ids = get_targeted_ad_group_ids(client, customer_id, resource_name)
# Create a new Promotion asset that matches the target extension feed item.
promotion_asset_resource_name = create_promotion_asset_from_feed(
client, customer_id, extension_feed_item
)
# Associate the new Promotion asset with the same campaigns as the original.
associate_asset_with_campaigns(
client, customer_id, promotion_asset_resource_name, campaign_ids
)
# Associate the new Promotion asset with the same ad groups as the original.
associate_asset_with_ad_groups(
client, customer_id, promotion_asset_resource_name, ad_group_ids
)
def get_extension_feed_item(client, customer_id, feed_item_id):
"""Gets the requested Promotion-type extension feed item.
Note that extension feed items pertain to feeds that were created by Google.
Use FeedService to instead retrieve a user-created Feed.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
feed_item_id: an extension feed item ID.
Returns:
an ExtensionFeedItem instance.
"""
ga_service = client.get_service("GoogleAdsService")
query = f"""
SELECT
extension_feed_item.id,
extension_feed_item.ad_schedules,
extension_feed_item.device,
extension_feed_item.status,
extension_feed_item.start_date_time,
extension_feed_item.end_date_time,
extension_feed_item.targeted_campaign,
extension_feed_item.targeted_ad_group,
extension_feed_item.promotion_feed_item.discount_modifier,
extension_feed_item.promotion_feed_item.final_mobile_urls,
extension_feed_item.promotion_feed_item.final_url_suffix,
extension_feed_item.promotion_feed_item.final_urls,
extension_feed_item.promotion_feed_item.language_code,
extension_feed_item.promotion_feed_item.money_amount_off.amount_micros,
extension_feed_item.promotion_feed_item.money_amount_off.currency_code,
extension_feed_item.promotion_feed_item.occasion,
extension_feed_item.promotion_feed_item.orders_over_amount.amount_micros,
extension_feed_item.promotion_feed_item.orders_over_amount.currency_code,
extension_feed_item.promotion_feed_item.percent_off,
extension_feed_item.promotion_feed_item.promotion_code,
extension_feed_item.promotion_feed_item.promotion_end_date,
extension_feed_item.promotion_feed_item.promotion_start_date,
extension_feed_item.promotion_feed_item.promotion_target,
extension_feed_item.promotion_feed_item.tracking_url_template
FROM extension_feed_item
WHERE
extension_feed_item.extension_type = 'PROMOTION'
AND extension_feed_item.id = {feed_item_id}
LIMIT 1"""
# Issue a search request to get the extension feed item contents.
stream = ga_service.search_stream(customer_id=customer_id, query=query)
try:
stream_response = next(stream)
except StopIteration:
print(f"Error: No ExtensionFeedItem found with ID {feed_item_id}.")
sys.exit(1)
extension_feed_item = stream_response.results[0].extension_feed_item
print(
"Retrieved details for ad extension with ID: {extension_feed_item.id}."
)
# Create a query to retrieve any URL customer parameters attached to the
# extension feed item.
url_custom_params_query = f"""
SELECT
feed_item.url_custom_parameters
FROM feed_item
WHERE feed_item.id = {extension_feed_item.id}"""
# Issue a search request to get any URL custom parameters.
stream = ga_service.search_stream(
customer_id=customer_id, query=url_custom_params_query
)
try:
url_stream_response = next(stream)
except StopIteration:
print(f"Error: No FeedItems found with ID {feed_item_id}.")
sys.exit(1)
feed_item = url_stream_response.results[0].feed_item
parameters = feed_item.url_custom_parameters
num_params = len(parameters)
print(f"Retrieved {num_params} attached URL custom parameters.")
if num_params > 0:
extension_feed_item.promotion_feed_item.url_custom_parameters.extend(
parameters
)
return extension_feed_item
def get_targeted_campaign_ids(client, customer_id, resource_name):
"""Retrieves all campaigns associated with the given FeedItem resource name.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
resource_name: an extension feed item resource name.
Returns:
a list of campaign IDs.
"""
ga_service = client.get_service("GoogleAdsService")
query = """
SELECT
campaign.id,
campaign_extension_setting.extension_feed_items
FROM campaign_extension_setting
WHERE
campaign_extension_setting.extension_type = 'PROMOTION'
AND campaign.status != 'REMOVED'"""
stream = ga_service.search_stream(customer_id=customer_id, query=query)
campaign_ids = []
for batch in stream:
for row in batch.results:
feed_items = row.campaign_extension_setting.extension_feed_items
if resource_name in feed_items:
print(f"Found matching campaign with ID: '{row.campaign.id}'")
campaign_ids.append(row.campaign.id)
return campaign_ids
def get_targeted_ad_group_ids(client, customer_id, resource_name):
"""Retrieves all ad groups associated with the given FeedItem resource name.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
resource_name: an extension feed item resource name.
Returns:
a list of ad group IDs.
"""
ga_service = client.get_service("GoogleAdsService")
query = """
SELECT
ad_group.id,
ad_group_extension_setting.extension_feed_items
FROM ad_group_extension_setting
WHERE
ad_group_extension_setting.extension_type = 'PROMOTION'
AND ad_group.status != 'REMOVED'"""
stream = ga_service.search_stream(customer_id=customer_id, query=query)
ad_group_ids = []
for batch in stream:
for row in batch.results:
feed_items = row.ad_group_extension_setting.extension_feed_items
if resource_name in feed_items:
print(f"Found matching ad group with ID: '{row.ad_group.id}'")
ad_group_ids.append(row.ad_group.id)
return ad_group_ids
def create_promotion_asset_from_feed(client, customer_id, extension_feed_item):
"""Retrieves all campaigns associated with the given FeedItem resource name.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
extension_feed_item: an extension feed item.
Returns:
the resource name of a newly created promotion asset.
"""
asset_service = client.get_service("AssetService")
promotion_feed_item = extension_feed_item.promotion_feed_item
# Create an asset operation to start building the new promotion asset using
# data from the given extension feed item.
asset_operation = client.get_type("AssetOperation")
asset = asset_operation.create
asset.name = f"Migrated from feed item ID '{extension_feed_item.id}'"
asset.tracking_url_template = promotion_feed_item.tracking_url_template
asset.final_url_suffix = promotion_feed_item.final_url_suffix
asset.final_urls.extend(promotion_feed_item.final_urls)
asset.final_mobile_urls.extend(promotion_feed_item.final_mobile_urls)
promotion_asset = asset.promotion_asset
promotion_asset.promotion_target = promotion_feed_item.promotion_target
promotion_asset.discount_modifier = promotion_feed_item.discount_modifier
promotion_asset.redemption_start_date = (
promotion_feed_item.promotion_start_date
)
promotion_asset.redemption_end_date = promotion_feed_item.promotion_end_date
promotion_asset.occasion = promotion_feed_item.occasion
promotion_asset.language_code = promotion_feed_item.language_code
promotion_asset.ad_schedule_targets.extend(extension_feed_item.ad_schedules)
# Either percent_off or money_amount_off must be set.
if promotion_feed_item.percent_off > 0:
# Adjust the percent off scale after copying. Extension feed items
# interpret 1,000,000 as 1% and assets interpret 1,000,000 as 100% so
# to migrate the correct discount value we must divide it by 100.
promotion_asset.percent_off = int(promotion_feed_item.percent_off / 100)
else:
# If percent_off is not set then copy money_amount_off. This field is
# an instance of Money in both cases, so setting the field with
# copy_from is possible. Using regular assignment is also valid here.
client.copy_from(
promotion_asset.money_amount_off,
promotion_feed_item.money_amount_off,
)
# Check if promotion_code field is set
if promotion_feed_item.promotion_code:
promotion_asset.promotion_code = promotion_feed_item.promotion_code
else:
# If promotion_code is not set then copy orders_over_amount. This field
# is an instance of Money in both cases, so setting the field with
# copy_from is possible. Using regular assignment is also valid here.
client.copy_from(
promotion_asset.orders_over_amount,
promotion_feed_item.orders_over_amount,
)
# Set the start and end dates if set in the existing extension.
if promotion_feed_item.promotion_start_date:
promotion_asset.start_date = promotion_feed_item.promotion_start_date
if promotion_feed_item.promotion_end_date:
promotion_asset.end_date = promotion_feed_item.promotion_end_date
response = asset_service.mutate_assets(
customer_id=customer_id, operations=[asset_operation]
)
resource_name = response.results[0].resource_name
print(f"Created promotion asset with resource name: '{resource_name}'")
return resource_name
def associate_asset_with_campaigns(
client, customer_id, promotion_asset_resource_name, campaign_ids
):
"""Associates the specified promotion asset with the specified campaigns.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
promotion_asset_resource_name: the resource name for a promotion asset.
campaign_ids: a list of campaign IDs.
"""
if len(campaign_ids) == 0:
print(f"Asset was not associated with any campaigns.")
return
campaign_service = client.get_service("CampaignService")
campaign_asset_service = client.get_service("CampaignAssetService")
operations = []
for campaign_id in campaign_ids:
operation = client.get_type("CampaignAssetOperation")
campaign_asset = operation.create
campaign_asset.asset = promotion_asset_resource_name
campaign_asset.field_type = client.enums.AssetFieldTypeEnum.PROMOTION
campaign_asset.campaign = campaign_service.campaign_path(
customer_id, campaign_id
)
operations.append(operation)
response = campaign_asset_service.mutate_campaign_assets(
customer_id=customer_id, operations=operations
)
for result in response.results:
print(
"Created campaign asset with resource name: "
f"'{result.resource_name}'"
)
def associate_asset_with_ad_groups(
client, customer_id, promotion_asset_resource_name, ad_group_ids
):
"""Associates the specified promotion asset with the specified campaigns.
Args:
client: an initialized GoogleAdsClient instance.
customer_id: a client customer ID.
promotion_asset_resource_name: the resource name for a promotion asset.
ad_groups_ids: a list of ad group IDs.
"""
if len(ad_group_ids) == 0:
print(f"Asset was not associated with any ad groups.")
return
ad_group_service = client.get_service("AdGroupService")
ad_group_asset_service = client.get_service("AdGroupAssetService")
operations = []
for ad_group_id in ad_group_ids:
operation = client.get_type("AdGroupAssetOperation")
ad_group_asset = operation.create
ad_group_asset.asset = promotion_asset_resource_name
ad_group_asset.field_type = client.enums.AssetFieldTypeEnum.PROMOTION
ad_group_asset.ad_group = ad_group_service.ad_group_path(
customer_id, ad_group_id
)
operations.append(operation)
response = ad_group_asset_service.mutate_ad_group_assets(
customer_id=customer_id, operations=operations
)
for result in response.results:
print(
"Created ad group asset with resource name: "
f"'{result.resource_name}'"
)
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="v13")
parser = argparse.ArgumentParser(
description="Migrates a feed-based promotion extension to an "
"asset-based extension."
)
# 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(
"-f",
"--feed_item_id",
type=str,
required=True,
help="The ID of the ExtensionFeedItem to migrate.",
)
args = parser.parse_args()
try:
main(googleads_client, args.customer_id, args.feed_item_id)
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 2021 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 code example retrieves the full details of a Promotion Feed-based extension and
# creates a matching Promotion asset-based extension. The new Asset-based extension will
# then be associated with the same campaigns and ad groups as the original Feed-based
# extension.
#
# Once copied, you should remove the Feed-based extension; see
# remove_entire_sitelink_campaign_extension_setting.rb.cs for an example.
require 'optparse'
require 'google/ads/google_ads'
def migrate_promotion_feed_to_asset(customer_id, feed_item_id)
# GoogleAdsClient will read a config file from
# ENV['HOME']/google_ads_config.rb when called without parameters
client = Google::Ads::GoogleAds::GoogleAdsClient.new
resource_name = client.path.extension_feed_item(customer_id, feed_item_id)
# Get the target extension feed item.
extension_feed_item = get_extension_feed_item(client, customer_id, feed_item_id)
# Get all campaign IDs associated with the extension feed item.
campaign_ids = get_targeted_campaign_ids(client, customer_id, resource_name)
# Get all ad group IDs associated with the extension feed item.
ad_group_ids = get_targeted_ad_group_ids(client, customer_id, resource_name)
# Create a new Promotion asset that matches the target extension feed item.
promotion_asset_resource_name = create_promotion_asset_from_feed(client, customer_id, extension_feed_item)
# Associate the new Promotion asset with the same campaigns as the original.
associate_asset_with_campaigns(client, customer_id, promotion_asset_resource_name, campaign_ids)
# Associate the new Promotion asset with the same ad groups as the original.
associate_asset_with_ad_groups(client, customer_id, promotion_asset_resource_name, ad_group_ids)
end
def get_extension_feed_item(client, customer_id, feed_item_id)
# Gets the requested Promotion-type extension feed item.
#
# Note that extension feed items pertain to feeds that were created by Google. Use
# FeedService to instead retrieve a user-created Feed.
google_ads_service = client.service.google_ads
query = <<~QUERY
SELECT
extension_feed_item.id,
extension_feed_item.ad_schedules,
extension_feed_item.device,
extension_feed_item.status,
extension_feed_item.start_date_time,
extension_feed_item.end_date_time,
extension_feed_item.targeted_campaign,
extension_feed_item.targeted_ad_group,
extension_feed_item.promotion_feed_item.discount_modifier,
extension_feed_item.promotion_feed_item.final_mobile_urls,
extension_feed_item.promotion_feed_item.final_url_suffix,
extension_feed_item.promotion_feed_item.final_urls,
extension_feed_item.promotion_feed_item.language_code,
extension_feed_item.promotion_feed_item.money_amount_off.amount_micros,
extension_feed_item.promotion_feed_item.money_amount_off.currency_code,
extension_feed_item.promotion_feed_item.occasion,
extension_feed_item.promotion_feed_item.orders_over_amount.amount_micros,
extension_feed_item.promotion_feed_item.orders_over_amount.currency_code,
extension_feed_item.promotion_feed_item.percent_off,
extension_feed_item.promotion_feed_item.promotion_code,
extension_feed_item.promotion_feed_item.promotion_end_date,
extension_feed_item.promotion_feed_item.promotion_start_date,
extension_feed_item.promotion_feed_item.promotion_target,
extension_feed_item.promotion_feed_item.tracking_url_template
FROM extension_feed_item
WHERE
extension_feed_item.extension_type = 'PROMOTION'
AND extension_feed_item.id = #{feed_item_id}
LIMIT 1
QUERY
# Issue a search request to get the extension feed item contents.
response = google_ads_service.search(customer_id: customer_id, query: query)
extension_feed_item = response.first&.extension_feed_item
if extension_feed_item.nil?
raise "Error: No ExtensionFeedItem found with ID '#{feed_item_id}'."
end
puts "Retrieved details for ad extension with ID '#{extension_feed_item.id}'."
# Create a query to retrieve any URL customer parameters attached to the
# extension feed item.
query = <<~QUERY
SELECT feed_item.url_custom_parameters
FROM feed_item
WHERE feed_item.id = #{extension_feed_item.id}
LIMIT 1
QUERY
# Issue a search request to get any URL custom parameters.
response = google_ads_service.search(customer_id: customer_id, query: query)
feed_item = response.first&.feed_item
if feed_item.nil?
raise "Error: No FeedItem found with ID '#{feed_item_id}'."
end
parameters = feed_item.url_custom_parameters
puts "Retrieved #{parameters.count} attached URL custom parameters."
extension_feed_item.promotion_feed_item.url_custom_parameters += parameters
extension_feed_item
end
def get_targeted_campaign_ids(client, customer_id, resource_name)
# Finds and returns all of the campaigns that are associated with the specified
# Promotion extension feed item.
query = <<~QUERY
SELECT
campaign.id,
campaign_extension_setting.extension_feed_items
FROM campaign_extension_setting
WHERE
campaign_extension_setting.extension_type = 'PROMOTION'
AND campaign.status != 'REMOVED'
QUERY
responses = client.service.google_ads.search_stream(customer_id: customer_id, query: query)
campaign_ids = []
responses.each do |response|
response.results.each do |row|
feed_items = row.campaign_extension_setting.extension_feed_items
if feed_items.include?(resource_name)
puts "Found matching campaign with ID '#{row.campaign.id}'."
campaign_ids << row.campaign.id
end
end
end
campaign_ids
end
def get_targeted_ad_group_ids(client, customer_id, resource_name)
# Finds and returns all of the ad groups that are associated with the specified
# Promotion extension feed item.
query = <<~QUERY
SELECT
ad_group.id,
ad_group_extension_setting.extension_feed_items
FROM ad_group_extension_setting
WHERE
ad_group_extension_setting.extension_type = 'PROMOTION'
AND ad_group.status != 'REMOVED'
QUERY
responses = client.service.google_ads.search_stream(customer_id: customer_id, query: query)
ad_group_ids = []
responses.each do |response|
response.results.each do |row|
feed_items = row.ad_group_extension_setting.extension_feed_items
if feed_items.include?(resource_name)
puts "Found matching ad group with ID: '#{row.ad_group.id}'"
ad_group_ids << row.ad_group.id
end
end
end
ad_group_ids
end
def create_promotion_asset_from_feed(client, customer_id, extension_feed_item)
# Create a Promotion asset that copies values from the specified extension feed item.
asset_service = client.service.asset
promotion_feed_item = extension_feed_item.promotion_feed_item
# Create an asset operation to start building the new promotion asset using
# data from the given extension feed item.
asset_operation = client.operation.create_resource.asset do |asset|
asset.name = "Migrated from feed item ID '#{extension_feed_item.id}'"
asset.tracking_url_template = promotion_feed_item.tracking_url_template
asset.final_url_suffix = promotion_feed_item.final_url_suffix
asset.final_urls += promotion_feed_item.final_urls
asset.final_mobile_urls += promotion_feed_item.final_mobile_urls
# Create the Promotion asset.
asset.promotion_asset = client.resource.promotion_asset do |pa|
pa.promotion_target = promotion_feed_item.promotion_target
pa.discount_modifier = promotion_feed_item.discount_modifier
pa.redemption_start_date = promotion_feed_item.promotion_start_date
pa.redemption_end_date = promotion_feed_item.promotion_end_date
pa.occasion = promotion_feed_item.occasion
pa.language_code = promotion_feed_item.language_code
pa.ad_schedule_targets += extension_feed_item.ad_schedules
# Either percent_off or money_amount_off must be set.
if promotion_feed_item.percent_off.positive?
# Adjust the percent off scale after copying.
pa.percent_off = int(promotion_feed_item.percent_off / 100)
else
# If percent_off is not set then copy money_amount_off. This field is
# an instance of Money in both cases, so setting the field with
# copy_from is possible. Using regular assignment is also valid here.
pa.money_amount_off = promotion_feed_item.money_amount_off
end
# Either promotion_code or orders_over_amount must be set.
if promotion_feed_item.promotion_code.empty?
pa.orders_over_amount = promotion_feed_item.orders_over_amount
else
pa.promotion_code = promotion_feed_item.promotion_code
end
# Set the start and end dates if set in the existing extension.
unless promotion_feed_item.promotion_start_date.empty?
pa.start_date = promotion_feed_item.promotion_start_date
end
unless promotion_feed_item.promotion_end_date.empty?
pa.end_date = promotion_feed_item.promotion_end_date
end
end
end
response = asset_service.mutate_assets(customer_id: customer_id, operations: [asset_operation])
resource_name = response.results.first.resource_name
puts "Created promotion asset with resource name: '#{resource_name}'"
resource_name
end
def associate_asset_with_campaigns(client, customer_id, promotion_asset_resource_name, campaign_ids)
# Associates the specified promotion asset with the specified campaigns.
if campaign_ids.empty?
puts 'Asset was not associated with any campaigns.'
return
end
operations = campaign_ids.map do |campaign_id|
client.operation.create_resource.campaign_asset do |ca|
ca.asset = promotion_asset_resource_name
ca.field_type = :PROMOTION
ca.campaign = client.path.campaign(customer_id, campaign_id)
end
end
response = client.service.campaign_asset.mutate_campaign_assets(
customer_id: customer_id,
operations: operations,
)
response.results.each do |result|
puts "Created campaign asset with resource name '#{result.resource_name}'."
end
end
def associate_asset_with_ad_groups(client, customer_id, promotion_asset_resource_name, ad_group_ids)
# Associates the specified promotion asset with the specified ad groups.
if ad_group_ids.empty?
puts 'Asset was not associated with any ad groups.'
return
end
operations = ad_group_ids.map do |ad_group_id|
client.operation.create_resource.ad_group_asset do |aga|
aga.asset = promotion_asset_resource_name
aga.field_type = :PROMOTION
aga.ad_group = client.path.ad_group(customer_id, ad_group_id)
end
end
response = client.service.ad_group_asset.mutate_ad_group_assets(
customer_id: customer_id,
operations: operations,
)
response.results.each do |result|
puts "Created ad group asset with resource name '#{result.resource_name}'."
end
end
if __FILE__ == $0
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[:feed_item_id] = 'INSERT_FEED_ITEM_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('-f', '--feed-item-id FEED-ITEM-ID', String, 'Feed Item ID') do |v|
options[:feed_item_id] = v
end
opts.separator ''
opts.separator 'Help:'
opts.on_tail('-h', '--help', 'Show this message') do
puts opts
exit
end
end.parse!
begin
migrate_promotion_feed_to_asset(options.fetch(:customer_id).tr('-', ''), options.fetch(:feed_item_id))
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 2021, 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 code example retrieves the full details of a Promotion Feed-based
# extension and creates a matching Promotion asset-based extension. The new
# Asset-based extension will then be associated with the same campaigns and ad
# groups as the original Feed-based extension.
#
# Once copied, you should remove the Feed-based extension; see
# remove_entire_sitelink_campaign_extension_setting.pl for an example.
use strict;
use warnings;
use utf8;
use FindBin qw($Bin);
use lib "$Bin/../../lib";
use Google::Ads::GoogleAds::Client;
use Google::Ads::GoogleAds::Utils::GoogleAdsHelper;
use Google::Ads::GoogleAds::Utils::SearchStreamHandler;
use Google::Ads::GoogleAds::V13::Resources::AdGroupAsset;
use Google::Ads::GoogleAds::V13::Resources::Asset;
use Google::Ads::GoogleAds::V13::Resources::CampaignAsset;
use Google::Ads::GoogleAds::V13::Common::Money;
use Google::Ads::GoogleAds::V13::Common::PromotionAsset;
use Google::Ads::GoogleAds::V13::Enums::ExtensionTypeEnum qw(PROMOTION);
use
Google::Ads::GoogleAds::V13::Services::AdGroupAssetService::AdGroupAssetOperation;
use Google::Ads::GoogleAds::V13::Services::AssetService::AssetOperation;
use
Google::Ads::GoogleAds::V13::Services::CampaignAssetService::CampaignAssetOperation;
use
Google::Ads::GoogleAds::V13::Services::GoogleAdsService::SearchGoogleAdsStreamRequest;
use Google::Ads::GoogleAds::V13::Utils::ResourceNames;
use Getopt::Long qw(:config auto_help);
use Pod::Usage;
use Cwd qw(abs_path);
# 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 $feed_item_id = "INSERT_FEED_ITEM_ID_HERE";
sub migrate_promotion_feed_to_asset {
my ($api_client, $customer_id, $feed_item_id) = @_;
# Get the GoogleAdsService client.
my $google_ads_service = $api_client->GoogleAdsService();
my $extension_feed_item_resource_name =
Google::Ads::GoogleAds::V13::Utils::ResourceNames::extension_feed_item(
$customer_id, $feed_item_id);
# Get the target extension feed item.
my $extension_feed_item =
get_extension_feed_item($google_ads_service, $customer_id, $feed_item_id);
# Get all campaign IDs associated with the extension feed item.
my @campaign_ids =
get_targeted_campaign_ids($google_ads_service, $customer_id,
$extension_feed_item_resource_name);
# Get all ad group IDs associated with the extension feed item.
my @ad_group_ids =
get_targeted_ad_group_ids($google_ads_service, $customer_id,
$extension_feed_item_resource_name);
# Create a new Promotion asset that matches the target extension feed item.
my $promotion_asset_resource_name =
create_promotion_asset_from_feed($api_client, $customer_id,
$extension_feed_item);
# Associate the new Promotion asset with the same campaigns as the original.
associate_asset_with_campaigns($api_client, $customer_id,
$promotion_asset_resource_name,
@campaign_ids);
# Associate the new Promotion asset with the same ad groups as the original.
associate_asset_with_ad_groups($api_client, $customer_id,
$promotion_asset_resource_name,
@ad_group_ids);
return 1;
}
# Gets the requested Promotion-type extension feed item.
#
# Note that extension feed items pertain to feeds that were created by Google.
# Use FeedService to instead retrieve a user-created Feed.
sub get_extension_feed_item {
my ($google_ads_service, $customer_id, $feed_item_id) = @_;
# Create a query that will retrieve the requested Promotion-type extension
# feed item and ensure that all fields are populated.
my $extension_feed_item_query = "
SELECT
extension_feed_item.id,
extension_feed_item.ad_schedules,
extension_feed_item.device,
extension_feed_item.status,
extension_feed_item.start_date_time,
extension_feed_item.end_date_time,
extension_feed_item.targeted_campaign,
extension_feed_item.targeted_ad_group,
extension_feed_item.promotion_feed_item.discount_modifier,
extension_feed_item.promotion_feed_item.final_mobile_urls,
extension_feed_item.promotion_feed_item.final_url_suffix,
extension_feed_item.promotion_feed_item.final_urls,
extension_feed_item.promotion_feed_item.language_code,
extension_feed_item.promotion_feed_item.money_amount_off.amount_micros,
extension_feed_item.promotion_feed_item.money_amount_off.currency_code,
extension_feed_item.promotion_feed_item.occasion,
extension_feed_item.promotion_feed_item.orders_over_amount.amount_micros,
extension_feed_item.promotion_feed_item.orders_over_amount.currency_code,
extension_feed_item.promotion_feed_item.percent_off,
extension_feed_item.promotion_feed_item.promotion_code,
extension_feed_item.promotion_feed_item.promotion_end_date,
extension_feed_item.promotion_feed_item.promotion_start_date,
extension_feed_item.promotion_feed_item.promotion_target,
extension_feed_item.promotion_feed_item.tracking_url_template
FROM extension_feed_item
WHERE
extension_feed_item.extension_type = 'PROMOTION'
AND extension_feed_item.id = $feed_item_id
LIMIT 1";
my $fetched_extension_feed_item;
# Issue a search request to get the extension feed item contents.
my $search_stream_request =
Google::Ads::GoogleAds::V13::Services::GoogleAdsService::SearchGoogleAdsStreamRequest
->new({
customerId => $customer_id,
query => $extension_feed_item_query
});
my $search_stream_handler =
Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({
service => $google_ads_service,
request => $search_stream_request
});
$search_stream_handler->process_contents(
sub {
my $google_ads_row = shift;
$fetched_extension_feed_item = $google_ads_row->{extensionFeedItem};
});
# Create a query to retrieve any URL customer parameters attached to the
# feed item.
my $url_custom_parameters_query = "
SELECT feed_item.url_custom_parameters
FROM feed_item
WHERE feed_item.id = $feed_item_id";
# Issue a search request to get any URL custom parameters.
$search_stream_request =
Google::Ads::GoogleAds::V13::Services::GoogleAdsService::SearchGoogleAdsStreamRequest
->new({
customerId => $customer_id,
query => $url_custom_parameters_query
});
$search_stream_handler =
Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({
service => $google_ads_service,
request => $search_stream_request
});
$search_stream_handler->process_contents(
sub {
my $google_ads_row = shift;
push
@{$fetched_extension_feed_item->{promotionFeedItem}{urlCustomParameters}
}, @{$google_ads_row->{feedItem}{urlCustomParameters}};
});
printf "Retrieved details for ad extension with ID %d.\n",
$fetched_extension_feed_item->{id};
return $fetched_extension_feed_item;
}
# Finds and returns all of the campaigns that are associated with the specified
# Promotion extension feed item.
sub get_targeted_campaign_ids {
my ($google_ads_service, $customer_id, $extension_feed_item_resource_name) =
@_;
my @campaign_ids;
my $query = "
SELECT campaign.id, campaign_extension_setting.extension_feed_items
FROM campaign_extension_setting
WHERE campaign_extension_setting.extension_type = 'PROMOTION'
AND campaign.status != 'REMOVED'";
my $search_stream_request =
Google::Ads::GoogleAds::V13::Services::GoogleAdsService::SearchGoogleAdsStreamRequest
->new({
customerId => $customer_id,
query => $query
});
my $search_stream_handler =
Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({
service => $google_ads_service,
request => $search_stream_request
});
$search_stream_handler->process_contents(
sub {
my $google_ads_row = shift;
# Add the campaign ID to the list of IDs if the extension feed item
# is associated with this extension setting.
if (grep { $_ eq $extension_feed_item_resource_name }
@{$google_ads_row->{campaignExtensionSetting}{extensionFeedItems}})
{
printf
"Found matching campaign with ID $google_ads_row->{campaign}{id}.\n";
push @campaign_ids, $google_ads_row->{campaign}{id};
}
});
return @campaign_ids;
}
# Finds and returns all of the ad groups that are associated with the specified
# Promotion extension feed item.
sub get_targeted_ad_group_ids {
my ($google_ads_service, $customer_id, $extension_feed_item_resource_name) =
@_;
my @ad_group_ids;
my $query = "
SELECT ad_group.id, ad_group_extension_setting.extension_feed_items
FROM ad_group_extension_setting
WHERE ad_group_extension_setting.extension_type = 'PROMOTION'
AND ad_group.status != 'REMOVED'";
my $search_stream_request =
Google::Ads::GoogleAds::V13::Services::GoogleAdsService::SearchGoogleAdsStreamRequest
->new({
customerId => $customer_id,
query => $query
});
my $search_stream_handler =
Google::Ads::GoogleAds::Utils::SearchStreamHandler->new({
service => $google_ads_service,
request => $search_stream_request
});
$search_stream_handler->process_contents(
sub {
my $google_ads_row = shift;
# Add the ad group ID to the list of IDs if the extension feed item
# is associated with this extension setting.
if (grep { $_ eq $extension_feed_item_resource_name }
@{$google_ads_row->{adGroupExtensionSetting}{extensionFeedItems}})
{
printf
"Found matching ad group with ID $google_ads_row->{adGroup}{id}.\n";
push @ad_group_ids, $google_ads_row->{adGroup}{id};
}
});
return @ad_group_ids;
}
# Create a Promotion asset that copies values from the specified extension feed
# item.
sub create_promotion_asset_from_feed {
my ($api_client, $customer_id, $extension_feed_item) = @_;
my $promotion_feed_item = $extension_feed_item->{promotionFeedItem};
# Create the Promotion asset.
my $asset = Google::Ads::GoogleAds::V13::Resources::Asset->new({
name => "Migrated from feed item #" . $extension_feed_item->{id},
trackingUrlTemplate => $promotion_feed_item->{trackingUrlTemplate},
finalUrlSuffix => $promotion_feed_item->{finalUrlSuffix},
promotionAsset =>
Google::Ads::GoogleAds::V13::Common::PromotionAsset->new({
promotionTarget => $promotion_feed_item->{promotionTarget},
discountModifier => $promotion_feed_item->{discountModifier},
redemptionStartDate => $promotion_feed_item->{promotionStartDate},
redemptionEndDate => $promotion_feed_item->{promotionEndDate},
occasion => $promotion_feed_item->{occasion},
languageCode => $promotion_feed_item->{languageCode}})});
push @{$asset->{finalUrls}}, @{$promotion_feed_item->{finalUrls}};
# Copy optional fields if present in the existing extension.
if (defined($extension_feed_item->{adSchedules})) {
push @{$asset->{promotionAsset}{adScheduleTargets}},
@{$extension_feed_item->{adSchedules}};
}
if (defined($promotion_feed_item->{finalMobileUrls})) {
push @{$asset->{finalMobileUrls}},
@{$promotion_feed_item->{finalMobileUrls}};
}
if (defined($promotion_feed_item->{urlCustomParameters})) {
push @{$asset->{urlCustomParameters}},
@{$promotion_feed_item->{urlCustomParameters}};
}
# Either percentOff or moneyAmountOff must be set.
if (defined($promotion_feed_item->{percentOff})) {
# Adjust the percent off scale when copying.
$asset->{promotionAsset}{percentOff} =
$promotion_feed_item->{percentOff} / 100;
} else {
$asset->{promotionAsset}{moneyAmountOff} =
Google::Ads::GoogleAds::V13::Common::Money->new({
amountMicros => $promotion_feed_item->{moneyAmountOff}{amountMicros},
currencyCode => $promotion_feed_item->{moneyAmountOff}{currencyCode}});
}
# Either promotionCode or ordersOverAmount must be set.
if (defined($promotion_feed_item->{promotionCode})) {
$asset->{promotionAsset}{promotionCode} =
$promotion_feed_item->{promotionCode};
} else {
$asset->{promotionAsset}{ordersOverAmount} =
Google::Ads::GoogleAds::V13::Common::Money->new({
amountMicros => $promotion_feed_item->{ordersOverAmount}{amountMicros},
currencyCode => $promotion_feed_item->{ordersOverAmount}{currencyCode}}
);
}
# Set the start and end dates if set in the existing extension.
if (defined($extension_feed_item->{startDateTime})) {
$asset->{promotionAsset}{startDate} =
substr($extension_feed_item->{startDateTime},
0, index($extension_feed_item->{startDateTime}, ' '));
}
if (defined($extension_feed_item->{endDateTime})) {
$asset->{promotionAsset}{endDate} =
substr($extension_feed_item->{endDateTime},
0, index($extension_feed_item->{endDateTime}, ' '));
}
# Build an operation to create the Promotion asset.
my $operation =
Google::Ads::GoogleAds::V13::Services::AssetService::AssetOperation->new({
create => $asset
});
# Issue the request and return the resource name of the new Promotion asset.
my $response = $api_client->AssetService()->mutate({
customerId => $customer_id,
operations => [$operation]});
printf
"Created Promotion asset with resource name '%s'.\n",
$response->{results}[0]{resourceName};
return $response->{results}[0]{resourceName};
}
# Associates the specified Promotion asset with the specified campaigns.
sub associate_asset_with_campaigns {
my ($api_client, $customer_id, $promotion_asset_resource_name, @campaign_ids)
= @_;
if (scalar(@campaign_ids) == 0) {
printf "Asset was not associated with any campaigns.\n";
return ();
}
my $operations = [];
foreach my $campaign_id (@campaign_ids) {
my $campaign_asset =
Google::Ads::GoogleAds::V13::Resources::CampaignAsset->new({
asset => $promotion_asset_resource_name,
fieldType => PROMOTION,
campaign => Google::Ads::GoogleAds::V13::Utils::ResourceNames::campaign(
$customer_id, $campaign_id
)});
my $operation =
Google::Ads::GoogleAds::V13::Services::CampaignAssetService::CampaignAssetOperation
->new({
create => $campaign_asset
});
push @$operations, $operation;
}
my $response = $api_client->CampaignAssetService()->mutate({
customerId => $customer_id,
operations => $operations
});
foreach my $result (@{$response->{results}}) {
printf "Created campaign asset with resource name '%s'.\n",
$result->{resourceName};
}
}
# Associates the specified Promotion asset with the specified ad groups.
sub associate_asset_with_ad_groups {
my ($api_client, $customer_id, $promotion_asset_resource_name, @ad_group_ids)
= @_;
if (scalar(@ad_group_ids) == 0) {
printf "Asset was not associated with any ad groups.\n";
return ();
}
my $operations = [];
foreach my $ad_group_id (@ad_group_ids) {
my $ad_group_asset =
Google::Ads::GoogleAds::V13::Resources::AdGroupAsset->new({
asset => $promotion_asset_resource_name,
fieldType => PROMOTION,
adGroup => Google::Ads::GoogleAds::V13::Utils::ResourceNames::ad_group(
$customer_id, $ad_group_id
)});
my $operation =
Google::Ads::GoogleAds::V13::Services::AdGroupAssetService::AdGroupAssetOperation
->new({
create => $ad_group_asset
});
push @$operations, $operation;
}
my $response = $api_client->AdGroupAssetService()->mutate({
customerId => $customer_id,
operations => $operations
});
foreach my $result (@{$response->{results}}) {
printf "Created ad group asset with resource name '%s'.\n",
$result->{resourceName};
}
}
# 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,
"feed_item_id=i" => \$feed_item_id
);
# 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, $feed_item_id);
# Call the example.
migrate_promotion_feed_to_asset($api_client, $customer_id =~ s/-//gr,
$feed_item_id);
=pod
=head1 NAME
migrate_promotion_feed_to_asset
=head1 DESCRIPTION
This code example retrieves the full details of a Promotion Feed-based extension
and creates a matching Promotion asset-based extension. The new Asset-based
extension will then be associated with the same campaigns and ad groups as the
original Feed-based extension.
Once copied, you should remove the Feed-based extension; see
remove_entire_sitelink_campaign_extension_setting.pl for an example.
=head1 SYNOPSIS
migrate_promotion_feed_to_asset.pl [options]
-help Show the help message.
-customer_id The Google Ads customer ID.
-feed_item_id ID of the ExtensionFeedItem to migrate.
=cut