使用欄位遮罩更新

在 Google Ads API 中,更新作業是透過欄位遮罩完成。欄位遮罩會列出您打算透過更新作業變更的所有欄位,且系統會忽略所有指定的欄位 (即使傳送至伺服器),除非這些欄位位於欄位遮罩中。

FieldMaskUtil

建議使用內建的欄位遮罩公用程式產生欄位遮罩,這項工具會隱藏特定詳細資料,並監控您對實體欄位所做的變更,自動產生欄位遮罩。

以下範例說明如何產生欄位遮罩,以更新廣告活動:

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

程式碼會先建立空白的 Campaign 物件,然後設定資源名稱,向 API 說明要更新的廣告活動。

這個範例會使用廣告活動的 client.field_mask.with 方法,開始更新所涵蓋的區塊。在這個區塊的結尾,公用程式會比較區塊前後廣告活動的目前狀態與初始狀態,並自動產生列舉已變更欄位的欄位遮罩。建構變動呼叫時,您可以將該欄位遮罩提供給作業,如下所示:

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

如果您要建構複雜的作業,並想精細控制每個步驟,建議使用這個方法。不過,在大多數情況下,您可以將資源名稱 (或現有資源例項) 傳遞至 Ruby 程式庫工廠方法:

campaign_resource_name = client.path.campaign(customer_id, campaign_id)

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

如果提供資源名稱字串,這個方法會自動建立新的廣告活動資源,並填入 resource_name,根據您在區塊中進行的變更建構欄位遮罩,建立更新作業,並傳回已填入 update 和 update_mask 的最終作業。您也可以傳遞現有的 Campaign Proto 執行個體,而非資源名稱字串,指定廣告活動的起始狀態。這個模式適用於所有支援更新作業的資源。

手動建立欄位遮罩

如要從頭建立欄位遮罩,而不使用程式庫公用程式,請建立 Google::Protobuf::FieldMask,並建立包含所有要變更欄位名稱的陣列,然後將該陣列指派給欄位遮罩的 paths 欄位:

mask = Google::Protobuf::FieldMask.new
mask.paths = ['status', 'name']

更新訊息欄位及其子欄位

MESSAGE 欄位可以有子欄位 (例如 MaximizeConversions,其中有三個:target_cpa_micros、cpc_bid_ceiling_micros 和 cpc_bid_floor_micros),也可以完全沒有子欄位 (例如 ManualCpm)。

沒有定義子欄位的訊息欄位

更新未定義任何子欄位的 MESSAGE 欄位時,請使用 FieldMaskUtil 產生欄位遮罩,如先前所述。

定義子欄位的訊息欄位

更新以子欄位定義的 MESSAGE 欄位時,如果未明確設定該訊息的任何子欄位,您必須手動將每個可變動的 MESSAGE 子欄位新增至 FieldMask,類似於先前從頭建立欄位遮罩的範例。

常見的例子是更新廣告活動的出價策略,但未在新出價策略中設定任何欄位。下列範例說明如何更新廣告活動,以使用 MaximizeConversions 出價策略,而不設定出價策略的任何子欄位。

在本例中,使用 FieldMaskUtil 的內建比較功能無法達成預期目標。

下列程式碼會產生包含 maximize_conversions 的欄位遮罩。不過,為避免不小心清除欄位,Google Ads API 不允許這種行為,且會產生 FieldMaskError.FIELD_HAS_SUBFIELDS 錯誤。

# 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 results 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]
)
# Create the operation directly from the campaign's resource name. Don't do
# anything in the block so that the field mask starts empty. You can modify
# other fields in this block, except the message field intended to have a
# blank subfield.
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]
)

清除欄位

部分欄位可明確清除。與上一個範例類似,您必須明確將這些欄位新增至欄位遮罩。舉例來說,假設您有一個廣告活動使用 MaximizeConversions 出價策略,且 target_cpa_micros 欄位的值大於 0。

在 proto3 中,將非選用純量欄位設為預設值 (0),與在新訊息例項中將其保留為未設定狀態,兩者無法區別。因此,FieldMaskUtil 會將 maximize_conversions 新增至欄位遮罩,而不是 maximize_conversions.target_cpa_micros,導致 FieldMaskError.FIELD_HAS_SUBFIELDS 錯誤。

# 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 includes 'maximize_conversions',
# but not 'maximize_conversions.target_cpa_micros', so it results 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 fails because the field mask is invalid.
response = client.service.campaign.mutate_campaigns(
  customer_id: customer_id,
  operations: [operation]
)
# Create a campaign including the maximize conversions fields right away, since
# they are manually added 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 can add a block here with
# other changes that are automatically 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 succeeds because the correct field mask is specified.
response = client.service.campaign.mutate_campaigns(
  customer_id: customer_id,
  operations: [operation]
)

請注意,對於在 Google Ads API 通訊協定緩衝區中定義為 optional 的欄位,自動比較方法會正常運作。由於 target_cpa_micros 不是 MaximizeConversions 上的 optional 欄位,因此必須明確將路徑附加至 update_mask.paths,才能清除該欄位。