Atualizações usando máscaras de campo

Na API Google Ads, as atualizações são feitas usando uma máscara de campo. A máscara de campo lista todos os campos que você pretende alterar com a atualização e todos os campos especificados que não estão na máscara de campo são ignorados, mesmo se forem enviados ao servidor.

FieldMaskUtil

A maneira recomendada de gerar máscaras de campo é usando nossa máscara de campo integrada utilitário que oculta muitos detalhes específicos e permite gerar campos mascara automaticamente ao monitorar as alterações feitas nos campos da entidade.

Confira como gerar uma máscara de campo para atualizar uma campanha:

campaign = client.resource.campaign
campaign.resource_name = client.path.campaign(customer_id, campaign_id)

mask = client.field_mask.with campaign do
  campaign.status = :PAUSED
  campaign.network_settings = client.resource.network_settings do |ns|
    ns.target_search_network = false
  end
end

O código primeiro cria um objeto de campanha vazio e, em seguida, define o nome do recurso para informar à API a campanha que está sendo atualizada.

Este exemplo usa o método client.field_mask.with na campanha para começar o bloco que engloba as atualizações. No final deste bloco, o utilitário compara o status atual da campanha após o bloqueio com o status da campanha antes do bloqueio e produz automaticamente um campo máscara enumerando os campos alterados. É possível fornecer essa máscara de campo à ao construí-lo para a chamada mutate da seguinte maneira:

operation = client.operation.campaign
operation.update = campaign
operation.update_mask = mask

Esse método é recomendado quando você está fazendo uma operação complicada e quer um bom controle sobre cada etapa. No entanto, na maioria dos casos, você pode usar o utilitário mais simples da biblioteca Ruby:

operation = client.operation.update_resource.campaign do |c|
  c.status = :PAUSED
  c.network_settings = client.resource.network_settings do |ns|
    ns.target_search_network = false
  end
end

Esse método cria automaticamente um novo recurso de campanha vazio, constrói máscara de campo com base nas alterações feitas dentro do bloco, cria a atualização operação e retorna a operação final com update e update_mask já preenchida. Também é possível transmitir uma campanha ao método campaign para especificar também o estado inicial da campanha. Esse padrão funciona para todos os recursos que oferecem suporte à operação de atualização.

Como criar uma máscara manualmente

Para criar uma máscara de campo do zero, sem usar nenhum utilitário da biblioteca, primeiro criaria um Google::Protobuf::FieldMask e depois uma matriz preenchida com os nomes de todos os campos que você pretende alterar e, por fim, atribua a matriz ao campo path da máscara de campo.

mask = Google::Protobuf::FieldMask.new
mask.path = ["status", "name"]

Como atualizar campos de mensagem e subcampos

Os campos MESSAGE podem ter subcampos (como MaximizeConversions, que tem três: target_cpa_micros, cpc_bid_ceiling_micros e cpc_bid_floor_micros) ou não será possível ter nenhuma (por exemplo, ManualCpm).

Campos de mensagem sem subcampos definidos

Ao atualizar um campo MESSAGE que não é definido com subcampos, use o FieldMaskUtil para gerar uma máscara de campo, conforme apresentado anteriormente.

Campos de mensagem com subcampos definidos

Ao atualizar um campo MESSAGE definido com subcampos sem definindo explicitamente qualquer um dos subcampos da mensagem, é necessário adicionar manualmente cada um dos subcampos mutáveis MESSAGE do FieldMask, semelhante aos exemplo anterior, que criou uma máscara de campo do zero.

Um exemplo comum é atualizar a estratégia de lances de uma campanha sem definir nenhum dos campos na nova estratégia. O exemplo a seguir demonstra como atualizar uma campanha para usar o MaximizeConversions estratégia de lances sem definir nenhum dos subcampos na estratégia de lances.

Para este exemplo, usar a comparação integrada do FieldMaskUtil não atingir a meta pretendida.

O código a seguir gera uma máscara de campo que inclui maximize_conversions. No entanto, a API do Google Ads não permite esse comportamento para impedir apagando acidentalmente campos e produz uma FieldMaskError.FIELD_HAS_SUBFIELDS erro.

# Creates a campaign with the proper resource name.
campaign = client.resource.campaign do |c|
  c.resource_name = client.path.campaign(customer_id, campaign_id)
end

# Update the maximize conversions field within the update block, so it's
# captured in the field mask
operation = client.operation.update_resource.campaign(campaign) do |c|
  c.maximize_conversions = client.resource.maximize_conversions
end

# Sends the operation in a mutate request that will result in a
# FieldMaskError.FIELD_HAS_SUBFIELDS error because empty MESSAGE fields cannot
# be included in a field mask.
response = client.service.campaign.mutate_campaigns(
  customer_id: customer_id,
  operations: [operation],
)

O código a seguir demonstra como atualizar corretamente uma campanha para usar a estratégia de lances MaximizeConversions sem definir nenhum dos subcampos.

# Create the operation directly from the campaign's resource name. Don't do
# anything in the block so that the field mask is empty. You could modify other
# fields in this block, just not the message field that is intended to have a
# blank subfield. We'll add that below.
campaign_resource_name = client.path.campaign(customer_id, campaign_id)
operation = client.operation.update_resource.campaign(campaign_resource_name) {}

# Manually add the maximize conversions subfield to the field mask so the API
# knows to clear it.
operation.update_mask.paths << "maximize_conversions.target_cpa_micros"

# This operation succeeds.
response = client.service.campaign.mutate_campaigns(
  customer_id: customer_id,
  operations: [operation],
)

Limpar campos

Alguns campos podem ser explicitamente apagados. Assim como no exemplo anterior, é preciso adicionar explicitamente esses campos à máscara de campo. Por exemplo, suponha que você tenha campanha que usa uma estratégia de lances de MaximizeConversions e que o O campo target_cpa_micros é definido com um valor maior que 0.

O código abaixo é executado. No entanto, o maximize_conversions.target_cpa_micros não é adicionado à máscara de campo, e nenhuma mudança é feita no campo target_cpa_micros:

# Create a campaign object representing the campaign you want to change.
campaign = client.resource.campaign do |c|
  c.resource_name = client.path.campaign(customer_id, campaign_id)
end

# The field mask in this operation will include 'maximize_conversions',
# but not 'maximize_conversions.target_cpa_micros', so it will result in an
# error.
operation = client.operation.update_resource.campaign(campaign) do |c|
  c.maximize_conversions = client.resource.maximize_conversions do |mc|
    mc.target_cpa_micros = 0
  end
end

# Operation will fail since field mask is incorrect.
response = client.service.campaign.mutate_campaigns(
  customer_id: customer_id,
  operations: [operation],
end

O código abaixo demonstra como limpar corretamente o target_cpa_micros. na estratégia de lances MaximizeConversions.

# Create a campaign including the maximize conversions fields right away, since
# we're going to manually add them to the field mask.
campaign = client.resource.campaign do |c|
  c.resource_name = client.path.campaign(customer_id, campaign_id)
  c.maximize_conversions = client.resource.maximize_conversions do |mc|
    mc.target_cpa_micros = 0
  end
end

# Create the operation with an empty field mask. You may add a block here with
# other changes that will automatically get added to the field mask.
operation = client.operation.update_resource.campaign(campaign) {}

# Add the field to the field mask so the API knows to clear it.
operation.update_mask.paths << 'maximize_conversions.target_cpa_micros'

# Operation will succeed since we specified the correct field mask.
response = client.service.campaign.mutate_campaigns(
  customer_id: customer_id,
  operations: [operation],
end

O valor "incorreto" funciona como pretendido nos campos definidos como optional na API Google Ads protocol buffers. Mas, como o target_cpa_micros é não é um campo optional, a marcação "incorreto" código não atualiza o lance para limpar o campo target_cpa.