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 の 3 つのサブフィールドがあります)を含めることができます。サブフィールドを含めないこともできます(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.target_cpa_micros ではなく maximize_conversions をフィールド マスクに追加するため、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 にパスを明示的に追加する必要があります。