Migração de extensões baseadas em recursos

Este documento descreve o processo de migração e desativação das extensões baseadas em feed. As extensões baseadas em feed serão migradas para novas extensões com base em recursos em lotes e serão totalmente desativadas em 2023.

Visão geral

O modelo de extensões baseado em feed foi descontinuado e substituído pelas extensões baseadas em recursos. As extensões baseadas em recursos reduzem a complexidade da criação e do gerenciamento de extensões. Essas ações são necessárias para manter o controle sobre suas extensões de anúncio.

O termo "extensão baseada em feed" se refere a qualquer um dos recursos ou funções associados aos seguintes serviços:

Se tanto as extensões com base em recursos quanto as baseadas em feed de um determinado tipo estiverem vinculadas ao mesmo cliente, campanha ou grupo de anúncios, as extensões com base em recursos serão veiculadas. Isso se aplica apenas para entidades no mesmo nível. Por exemplo, vincular um recurso a um grupo de anúncios impedirá que todos os feeds sejam veiculados nele, mas outros grupos na mesma campanha poderão continuar a veicular feeds. As extensões com base em recursos também aparecem por padrão na IU do Google Ads.

Se você tiver extensões ativas dos dois tipos, poderá ver uma notificação na página Extensões na IU do Google Ads, semelhante à captura de tela abaixo. As extensões "legadas" são baseadas no feed, enquanto as "atualizadas" são baseadas em recursos.

Tela de promoção atualizada

Depois de criar qualquer extensão com base em recursos, a visualização usará como padrão as extensões "atualizadas".

Detalhes da migração

Os feeds são migrados ao copiar os valores atuais para uma nova instância de extensão com base em recursos. As extensões atuais com base no feed serão copiadas automaticamente para as extensões com base em recursos em datas específicas. Todas as extensões baseadas em recursos terão novos valores de ID exclusivos.

Recomendamos que você mesmo realize o processo de migração usando a API Google Ads, conforme descrito neste guia, já que não haverá conexão entre os recursos criados durante a migração automática e os feeds originais.

Programação da migração

Todas as extensões baseadas em feed atuais serão migradas automaticamente para as extensões baseadas em recursos em lotes. As contas migradas vão rejeitar chamadas de mutação para entidades baseadas em feed.

O processo de migração automática criará extensões baseadas em recursos equivalentes às extensões atuais no feed e substituirá todas as ocorrências de AdGroupFeed, CampaignFeed e CustomerFeed por AdGroupAsset, CampaignAsset e CustomerAsset equivalentes. Se o grupo de anúncios, a campanha ou o cliente já tiver sido anexado a um recurso, o feed correspondente será ignorado.

Mudanças nas extensões baseadas em recursos

As extensões com base em recursos oferecem os mesmos recursos que as extensões com base em feed, mas alguns recursos foram removidos, incluindo as funções de correspondência e a maioria dos campos de segmentação.

  • Para segmentação, os campos de grupo de anúncios, campanha, palavra-chave, local e dispositivo móvel ficam indisponíveis para extensões baseadas em recursos.

  • Alguns campos não estão disponíveis em algumas extensões baseadas em recursos. Os campos a seguir foram removidos e não serão migrados automaticamente:

    • App: programações de anúncios
    • Ligação: horário de início, horário de término
    • Preço: horário de início, horário de término, programações de anúncios
    • Snippet estruturado: horário de início, horário de término, programações de anúncios
  • Todos os campos relacionados a datas agora estão no formato "aaaa-MM-dd". Não é possível especificar um horário do dia em qualquer campo de data em extensões baseadas em recursos.

  • Para extensões com base em recursos no futuro, recomendamos o uso de recursos de segmentação já disponíveis nos níveis da campanha e do grupo de anúncios. Para preferências de dispositivos móveis, considere incluir URLs compatíveis com dispositivos móveis em qualquer link.

Funções correspondentes

As funções de correspondência não estarão disponíveis para extensões baseadas em recursos. Durante a migração automática, apenas as seguintes funções correspondentes serão honradas:

Função correspondente Notas de migração
EQUALS(FEED_ITEM_ID, 1234567) Migrado no estado em que se encontra.
IN(FEED_ITEM_ID,{1234567,1234568,1234569}) Migrado no estado em que se encontra.
IDENTITY(false) Migrado como excluded_parent_asset_field_types.
IDENTITY(true) Migrado com todos os itens do feed vinculados, exceto um caso especial
AND(
IN(FEED_ITEM_ID,{1234567,1234568,1234569}),
EQUALS(CONTEXT.DEVICE,"Mobile"))
Migrado como IN(FEED_ITEM_ID,{1234567,1234568,1234569}).
AND(
EQUALS(FEED_ITEM_ID, 1234567),
EQUALS(CONTEXT.DEVICE,"Mobile"))
Migrado como EQUALS(FEED_ITEM_ID,1234567).

Caso especial IDENTITY(true)

Uma função correspondente IDENTITY(true) será ignorada durante a migração automática se estiver anexada a uma extensão e corresponder a mais de 20 itens de feed ativos. Atualize a função correspondente para a notação IN(FEED_ITEM_ID, {1234567,1234568,1234569}).

Também é possível migrar suas extensões por conta própria e vincular uma extensão baseada em recursos a outras entidades. Cada cliente, campanha e grupo de anúncios pode ser vinculado a até 20 extensões baseadas em recursos ativos do mesmo tipo de extensão. Consulte o procedimento de migração para ver informações sobre como migrar e vincular a extensões baseadas em recursos.

Considerações sobre o acompanhamento de chamadas

Os campos call_tracking_enabled e call_conversion_tracking_disabled foram removidos em CallAsset. O acompanhamento de chamadas agora é controlado no nível da conta usando CallReportingSetting. Use o campo CallAsset.call_conversion_reporting_state para ativar o acompanhamento de conversões nas extensões de chamada. O campo call_conversion_reporting_state pode ser definido como um dos seguintes valores:

  • DISABLED: nenhuma ação de conversão de chamada será realizada.
  • USE_ACCOUNT_LEVEL_CALL_CONVERSION_ACTION: a extensão usará o tipo de conversão de chamada definido no nível da conta.
  • USE_RESOURCE_LEVEL_CALL_CONVERSION_ACTION: a extensão usará a ação de conversão especificada no campo CallAsset.call_conversion_action. O campo CallAsset.call_conversion_action será ignorado para qualquer outro valor de call_conversion_reporting_state.

Ao migrar uma extensão de chamada baseada em feed, se call_conversion_tracking_disabled for true, call_conversion_reporting_state no novo CallAsset vai ser definido como DISABLED. O valor padrão de call_conversion_reporting_state é USE_RESOURCE_LEVEL_CALL_CONVERSION_ACTION. Defina-o explicitamente como DISABLED para continuar bloqueando o acompanhamento de conversões dessa extensão.

Se você migrar suas próprias extensões de chamada com base em feed e estiver usando o acompanhamento de conversões com anúncios de chamada para computador, migre todas as instâncias de extensão de chamada para extensões com base em recursos em uma conta ao mesmo tempo. Isso se deve à atribuição de números de encaminhamento de chamadas do Google, que só serão fornecidos às extensões de chamada com base em recursos quando estiverem presentes em uma conta.

Rastrear extensões com base em recursos usando parâmetros ValueTrack em URLs

Todos os parâmetros ValueTrack continuam funcionando quando usados em URLs em extensões baseadas em recursos, exceto {feeditemid}. Em vez disso, use o {extensionid} para vincular qualquer URL final, modelo de acompanhamento ou parâmetro personalizado a uma extensão baseada em recursos. O parâmetro {feeditemid} não retornará mais nenhum valor depois que a extensão baseada em feed for migrada para uma extensão baseada em recursos.

O procedimento de migração automática não vai mudar as ocorrências de {feeditemid} em {extensionid}. Atualize todos os URLs que usam o parâmetro {feeditemid} para incluir também o parâmetro {extensionid}. Isso garante o rastreamento dos cliques para qualquer tipo de extensão. No entanto, apenas um desses campos será preenchido quando ocorrer um clique.

Veiculação de extensões com base em recursos

As extensões com base em recursos são anexadas para serem veiculadas em campanhas com links para várias entidades.

AdGroupAsset
A extensão será veiculada neste grupo de anúncios.
CampaignAsset
A extensão será veiculada nessa campanha e em todos os grupos de anúncios dela.
CustomerAsset
A extensão será veiculada em qualquer campanha qualificada.

Isso é diferente em relação ao comportamento histórico:

AdGroupFeed
A extensão será veiculada neste grupo de anúncios.
CampaignFeed
A extensão será veiculada nessa campanha, exceto para grupos de anúncios com links para feeds de grupos de anúncios.
CustomerFeed
A extensão será veiculada em qualquer campanha ou grupo de anúncios qualificado, exceto campanhas e grupos de anúncios com extensões vinculadas a feeds de campanha ou de grupo de anúncios, respectivamente.

Em resumo, o anexo de nível inferior dos recursos modificaria os níveis mais altos anteriormente, mas a segmentação será aditiva daqui para frente.

Procedimento de migração

Para migrar uma extensão baseada em feed para uma extensão baseada em recurso, siga estas etapas:

  1. Identifique uma extensão com base em feed que você pretende continuar usando.
  2. Copie o conteúdo da extensão baseada em feed em uma nova instância da extensão baseada em recursos correspondente. Por exemplo, o conteúdo de um ExtensionFeedItem do tipo Promotion seria copiado para um novo objeto PromotionAsset.
  3. Associe a nova extensão com base em recursos aos mesmos grupos de anúncios e campanhas.
  4. Verifique se a extensão com base em recursos está configurada corretamente.
  5. Remova a extensão com base em feed da sua conta.

Depois de copiar uma extensão baseada em feed em uma extensão baseada em recursos, interrompa imediatamente qualquer manipulação dessa extensão por meio dos serviços relacionados a feeds listados acima.

Remova a extensão baseada em feed depois de verificar se ela foi copiada com precisão para uma extensão baseada em recurso.

Um tipo de extensão será totalmente migrado quando todos os itens do feed com um determinado PlaceholderType tiverem sido removidos. Consulte Remover extensões para mais orientações.

O exemplo a seguir explica cada etapa do processo acima com uma extensão de promoção.

Identificar extensões com base em feed

Para ver uma lista dos itens de feed afetados, você precisa executar algumas consultas GAQL nas suas contas. Disponibilizamos consultas da GAQL para ilustrar o caso geral abaixo.

Feeds nativos

Se a conta tiver feeds nativos, que usam Feed, FeedItem e FeedMapping, use as seguintes consultas para recuperar os itens do feed que precisam ser migrados.

Primeiro, recupere todos os feeds que têm um FeedMapping para o tipo de extensão de interesse.

SELECT
  feed_mapping.feed,
  feed_mapping.placeholder_type,
  feed_mapping.attribute_field_mappings
FROM feed_mapping
WHERE feed_mapping.placeholder_type IN (
  'CALLOUT',
  'PROMOTION',
  'SITELINK',
  'STRUCTURED_SNIPPET',
  'APP',
  'CALL',
  'PRICE'
)

Agora você pode usar a feed_mapping.feed para recuperar os objetos de interesse FeedItem.

SELECT feed_item.attribute_values
FROM feed_item
WHERE feed.resource_name = '<INSERT feed_mapping.feed>'

Em seguida, o feed_item.attribute_values será interpretado de acordo com os marcadores feed_mapping.attribute_field_mappings. Esses mapeamentos de campo informam como os campos de extensão são mapeados para feed_item.attribute_values.

Serviços de configuração de extensões

Quando suas extensões foram criadas pelos serviços de configuração de extensões (CustomerExtensionSettingService, CampaignExtensionSettingService, AdGroupExtensionSettingService etc.), é mais fácil receber os IDs de itens do feed.

Use a consulta da linguagem de consulta do Google Ads a seguir para solicitar IDs de item do feed de extensão ativos de um determinado tipo de extensão.

SELECT extension_feed_item.id
FROM extension_feed_item
WHERE extension_feed_item.status = 'ENABLED'
  AND extension_feed_item.extension_type = 'PROMOTION'

Os IDs retornados podem ser usados para buscar detalhes da extensão.

Buscar detalhes da extensão com base no feed

Depois de identificar uma extensão baseada em feed para migrar, solicite os detalhes completos usando o ID com outra consulta da linguagem de consulta do Google Ads.

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 = 123456789012
LIMIT 1

A ExtensionFeedItem retornada terá todos os valores definidos atualmente na extensão baseada em feed especificada que pode ser aplicada a uma extensão baseada em recursos.

Se usar parâmetros personalizados de URL, você precisará buscá-los usando uma consulta adicional de linguagem de consulta do Google Ads. Adicione os resultados à instância ExtensionFeedItem recuperada pela consulta anterior. O código do item do feed dessa consulta é igual ao código usado na consulta anterior.

SELECT feed_item.url_custom_parameters
FROM feed_item
WHERE feed_item.id = 123456789012

Criar uma extensão com base em recursos

Os valores buscados na etapa anterior podem ser aplicados a uma nova instância do recurso relevante.

Java

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;
  }
}
      

C#

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;
}
      

PHP

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;
}
      

Python

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


      

Ruby

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
      

Perl

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};
}
      

Associe o recurso a campanhas e grupos de anúncios

Agora o novo recurso pode ser associado aos mesmos clientes, campanhas e grupos de anúncios que a extensão original baseada em feed. Primeiro, busque os IDs de recursos associados à configuração da extensão.

Java

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;
}
      

C#

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;
}
      

PHP

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;
}
      

Python

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


      

Ruby

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
      

Perl

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;
}
      

Em seguida, crie e faça upload de um novo CampaignAsset, AdGroupAsset ou CustomerAsset para vincular o recurso a cada recurso.

Java

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

C#

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}.");
    }
}
      

PHP

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

Python

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}'"
        )


      

Ruby

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
      

Perl

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};
  }
}
      

Verificar o conteúdo do recurso

Use a consulta de linguagem de consulta do Google Ads a seguir para buscar o conteúdo de um recurso de promoção. Inspecione os resultados para confirmar que todos os campos relevantes foram copiados corretamente.

Nesse momento, as duas extensões idênticas estão ativas, mas a extensão com base em recursos será veiculada em vez da extensão com base no feed.

SELECT
  asset.id,
  asset.name,
  asset.type,
  asset.final_urls,
  asset.final_mobile_urls,
  asset.final_url_suffix,
  asset.tracking_url_template,
  asset.promotion_asset.promotion_target,
  asset.promotion_asset.discount_modifier,
  asset.promotion_asset.redemption_start_date,
  asset.promotion_asset.redemption_end_date,
  asset.promotion_asset.occasion,
  asset.promotion_asset.language_code,
  asset.promotion_asset.percent_off,
  asset.promotion_asset.money_amount_off.amount_micros,
  asset.promotion_asset.money_amount_off.currency_code,
  asset.promotion_asset.promotion_code,
  asset.promotion_asset.orders_over_amount.amount_micros,
  asset.promotion_asset.orders_over_amount.currency_code,
  asset.promotion_asset.start_date,
  asset.promotion_asset.end_date,
  asset.promotion_asset.ad_schedule_targets
FROM asset
WHERE asset.resource_name = 'customers/123456789/assets/123456789012'

Remover a extensão com base em feed

Depois de verificar se a extensão baseada em recursos reflete com precisão a extensão original baseada em feed, remova a extensão baseada em feed.

Todas as extensões com base no feed atuais serão migradas automaticamente nas datas de migração automática. Remova as extensões com base em feed após a migração para evitar várias ocorrências da mesma extensão.

Detecção de contas migradas automaticamente

A API retorna um FeedErrorEnum.FeedError.legacy_extension_type_read_only ao tentar modificar extensões em uma conta já migrada. Você pode detectar essas contas criando uma operação de mutação trivial para um dos serviços de feed, por exemplo, FeedItemService.

Defina o campo validate_only na solicitação apenas para verificar sem aplicar o resultado. A resposta indicará se a conta foi migrada automaticamente.

A migração está acontecendo em fases. Por isso, é possível que algumas extensões sejam migradas e outras não. Consulte as orientações acima na programação de migração para ver prazos específicos.

Disponibilidade dos relatórios de feed

Os relatórios do feed histórico estarão disponíveis até que a migração para os recursos de imagem e local seja concluída, em algum momento em 2024. Depois disso, a migração será desativada.

O conteúdo do recurso pode ser solicitado emitindo uma consulta da linguagem de consulta do Google Ads para o relatório asset. Esse tipo de relatório é parecido com o tipo de relatório extension_feed_item para extensões baseadas em feed.

As estatísticas de desempenho de uma extensão com base em recursos podem ser solicitadas emitindo uma consulta da linguagem de consulta do Google Ads ao relatório asset_field_type_view. Esse tipo de relatório é semelhante ao feed_placeholder_view para extensões baseadas em feed.

Perguntas frequentes

O que acontece com as extensões legadas que não são totalmente compatíveis com os recursos?

O recurso será criado sem os campos sem suporte. Por exemplo, a preferência de dispositivo não está mais disponível nos recursos. Portanto, as extensões com preferência de dispositivo serão migradas para um recurso sem a preferência de dispositivo.

O que acontece com as extensões legadas que não foram aprovadas na revisão da política de anúncios?

Tentaremos migrar as extensões com status reprovado. No entanto, isso pode falhar em alguns casos.

Se a revisão de política foi reprovada de forma síncrona, não vamos migrar o recurso. A maioria dos motivos de reprovação de política se encaixam nesse bucket. Por exemplo, texto muito longo, linguagem obscena e assim por diante.

Caso contrário, para aprovações de políticas mais detalhadas que acontecem de forma assíncrona, migraremos a extensão, mas ela poderá ser reprovada após a migração.

O que acontece com as métricas dos relatórios de extensões legadas?

As métricas serão redefinidas após a migração dos recursos. As métricas legadas ficarão disponíveis por um curto período após a migração, mas serão removidas em algum momento.

Se você adicionar um tipo de extensão de recurso, por exemplo, frase de destaque, outros tipos de extensão, como preço, ainda estarão qualificados para veiculação a partir de feeds?

Sim. O link só recebe upgrade para o tipo de extensão vinculada. Se você não tiver vinculado um tipo específico de extensão de recurso, as extensões com base em feed continuarão sendo veiculadas para esse tipo.

Da mesma forma, quando você vincular um tipo específico de extensão, os feeds não estarão mais qualificados para veiculação.

É possível ter uma combinação de feeds e recursos sendo veiculados na mesma campanha. Se um grupo de anúncios tiver um recurso vinculado e outro tiver um feed vinculado, ambos serão qualificados para veiculação.

Os itens do feed vão ser removidos pela migração automática do Google?

Não. Vamos remover o link de item do feed, por exemplo, CampaignFeed, mas não o item do feed original.

A migração automática do Google só vai migrar itens do feed de veiculação?

Não. Vamos migrar cada item do feed para o recurso, independentemente de o item estar ou não sendo exibido ativamente por um link de item de feed, por exemplo, CampaignFeed.