Page Summary
-
Updates in the Google Ads API require a field mask listing all intended changes, ignoring unspecified fields even if sent to the server.
-
The FieldMaskUtil is the recommended tool for generating field masks from a modified object rather than creating them manually.
-
When updating message fields with defined subfields without setting any subfields, you must manually add each mutable subfield to the FieldMask to avoid errors.
-
To clear a field, the safest method is to explicitly add that specific field to the field mask.
In the Google Ads API, updates are done using a field mask. The
field mask (google.protobuf.FieldMask) contains a list of field paths in
snake_case that you intend to change with the update. Any specified fields
that are not in the field mask are ignored, even if sent to the server.
FieldMasks utility
The recommended way to generate field masks in the Java client library is to use
the built-in FieldMasks utility class, which lets you generate field masks
from a modified object instead of building them from scratch.
Here's an example for updating a campaign:
// Creates a Campaign object with the proper resource name and any other
// changes.
Campaign campaign =
Campaign.newBuilder()
.setResourceName(ResourceNames.campaign(customerId, campaignId))
.setStatus(CampaignStatus.PAUSED)
.build();
// Constructs an operation that updates the campaign, using the
// FieldMasks.allSetFieldsOf utility to derive the update mask. This mask tells
// the Google Ads API which attributes of the campaign you want to change.
CampaignOperation operation =
CampaignOperation.newBuilder()
.setUpdate(campaign)
.setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
.build();
// Sends the operation in a mutate request.
MutateCampaignsResponse response =
campaignServiceClient.mutateCampaigns(
customerId.toString(), Collections.singletonList(operation));
This example first creates an empty Campaign builder and sets its resource
name so that the API knows which campaign is being updated.
The example then calls FieldMasks.allSetFieldsOf() on the campaign to
automatically produce a field mask that enumerates all set fields. You can pass
the returned mask directly to the update call.
If you need to work with an existing object and update a few fields, use
FieldMasks.compare() as follows:
// Assumes existingCampaign was retrieved from a previous API call.
// Creates a new campaign based on the existing campaign and updates the
// campaign by setting its status to paused.
Campaign campaignToUpdate =
existingCampaign.toBuilder()
.setStatus(CampaignStatus.PAUSED)
.build();
// Constructs an operation that updates the campaign, using the
// FieldMasks.compare utility to derive the update mask. This mask tells the
// Google Ads API which attributes of the campaign you want to change.
CampaignOperation operation =
CampaignOperation.newBuilder()
.setUpdate(campaignToUpdate)
.setUpdateMask(FieldMasks.compare(existingCampaign, campaignToUpdate))
.build();
// Sends the operation in a mutate request.
MutateCampaignsResponse response =
campaignServiceClient.mutateCampaigns(
customerId.toString(), Collections.singletonList(operation));
To create a field mask from scratch, create a FieldMask
builder and add the snake_case name of each field you intend to change:
FieldMask fieldMask =
FieldMask.newBuilder()
.addPaths("status")
.addPaths("name")
.build();
Update message fields and their subfields
MESSAGE fields can have subfields (such as
MaximizeConversions, which has
target_cpa_micros, cpc_bid_ceiling_micros, and cpc_bid_floor_micros), or
they can have no subfields (such as ManualCpm).
Message fields with no defined subfields
When updating a MESSAGE field that is not defined with any subfields, use the
FieldMasks utility to generate a field mask, as described in the preceding
section.
Message fields with defined subfields
When updating a MESSAGE field that has defined subfields without explicitly
setting any of the subfields on that message, you must manually add each of the
mutable MESSAGE subfields to the FieldMask, similar to creating a field
mask from scratch.
One common example is updating a campaign's bidding strategy (oneof field
campaign_bidding_strategy) without setting any of the fields on the new
bidding strategy. The following example demonstrates how to update a campaign to
use the MaximizeConversions bidding
strategy without setting any of the subfields on the bidding strategy.
In this case, using the allSetFieldsOf() and compare() methods of
FieldMasks alone doesn't achieve the intended goal.
The following example generates a field mask that includes
maximize_conversions. However, the Google Ads API doesn't allow top-level message
paths that have subfields in an update mask (to prevent accidentally clearing
subfields) and returns a FieldMaskError.FIELD_HAS_SUBFIELDS
error.
// Creates a campaign with the proper resource name and an empty
// MaximizeConversions field.
Campaign campaign =
Campaign.newBuilder()
.setResourceName(ResourceNames.campaign(customerId, campaignId))
.setMaximizeConversions(MaximizeConversions.newBuilder().build())
.build();
// Constructs an operation using FieldMasks.allSetFieldsOf to derive the update
// mask. The field mask includes 'maximize_conversions', which produces a
// FieldMaskError.FIELD_HAS_SUBFIELDS error.
CampaignOperation operation =
CampaignOperation.newBuilder()
.setUpdate(campaign)
.setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
.build();
// Sends the operation in a mutate request that results in a
// FieldMaskError.FIELD_HAS_SUBFIELDS error because empty MESSAGE fields with
// subfields cannot be included directly in a field mask.
MutateCampaignsResponse response =
campaignServiceClient.mutateCampaigns(
customerId.toString(), Collections.singletonList(operation));
The following example demonstrates how to properly update a campaign to use the
MaximizeConversions bidding strategy without setting any of its subfields.
Learn more about
assigning standard and portfolio bidding strategies.
// Creates a Campaign object with the proper resource name.
Campaign campaign =
Campaign.newBuilder()
.setResourceName(ResourceNames.campaign(customerId, campaignId))
.build();
// Creates a field mask from the campaign and adds the mutable subfield
// ('maximize_conversions.target_cpa_micros') on the MaximizeConversions
// bidding strategy to the field mask. Because this subfield is included in the
// field mask while excluded from the campaign object, the Google Ads API
// switches the campaign's bidding strategy oneof to MaximizeConversions with
// target_cpa_micros unset.
FieldMask fieldMask =
FieldMasks.allSetFieldsOf(campaign).toBuilder()
.addPaths("maximize_conversions.target_cpa_micros")
.build();
// Creates an operation to update the campaign with the specified fields.
CampaignOperation operation =
CampaignOperation.newBuilder()
.setUpdate(campaign)
.setUpdateMask(fieldMask)
.build();
Clear fields
Some fields can be explicitly cleared. Similar to the preceding example, you
must explicitly add these fields to the field mask while leaving them unset on
the message object. For example, assume you have a campaign that uses a
MaximizeConversions bidding strategy and that the target_cpa_micros field is
set with a value greater than 0.
The following code runs, but maximize_conversions.target_cpa_micros won't be
cleared as intended:
// Creates a campaign with the proper resource name and a MaximizeConversions
// object with target_cpa_micros set to 0L.
Campaign campaign =
Campaign.newBuilder()
.setResourceName(ResourceNames.campaign(customerId, campaignId))
.setMaximizeConversions(
MaximizeConversions.newBuilder().setTargetCpaMicros(0L).build())
.setStatus(CampaignStatus.PAUSED)
.build();
// Constructs an operation using FieldMasks.allSetFieldsOf to derive the
// update mask.
CampaignOperation operation =
CampaignOperation.newBuilder()
.setUpdate(campaign)
.setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
.build();
// Sends the operation in a mutate request that does not clear the field
// cleanly.
MutateCampaignsResponse response =
campaignServiceClient.mutateCampaigns(
customerId.toString(), Collections.singletonList(operation));
The next example demonstrates how to properly clear the target_cpa_micros
field on the MaximizeConversions bidding strategy.
// Creates a Campaign object with the proper resource name.
Campaign campaign =
Campaign.newBuilder()
.setResourceName(ResourceNames.campaign(customerId, campaignId))
.build();
// Constructs a field mask from the campaign and adds the
// 'maximize_conversions.target_cpa_micros' field to the field mask, which
// clears this field from the bidding strategy without impacting any other
// fields on the bidding strategy.
FieldMask fieldMask =
FieldMasks.allSetFieldsOf(campaign).toBuilder()
.addPaths("maximize_conversions.target_cpa_micros")
.build();
// Creates an operation to update the campaign with the specified field.
CampaignOperation operation =
CampaignOperation.newBuilder()
.setUpdate(campaign)
.setUpdateMask(fieldMask)
.build();