Field Masks

  • Starting with version 19.0.0, the Google Ads API client library for .NET will no longer support .NET 5.0, requiring an upgrade before the end of 2024 for continued functionality.

  • The Google Ads API uses field masks to specify which fields to update during an operation, ignoring any unspecified fields.

  • The FieldMaskUtil provides methods like AllSetFieldsOf and FromChanges to help generate field masks automatically from objects.

  • When updating MESSAGE fields with subfields without setting the subfields explicitly, manually add the mutable subfields to the FieldMask to avoid errors.

  • To clear a field, explicitly add it to the field mask for consistent and reliable behavior, even if the field is defined as optional.

In the Google Ads API, a field mask is used to provide a list of fields that an API request should update. Any field that is not specified in the field mask will be ignored, even if sent to the server.

FieldMaskUtil class

The recommended way to generate field masks is to use the built-in FieldMaskUtil 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, that uses the FieldMasks.AllSetFieldsOf method to produce a field mask that enumerates all the set fields. You can then pass the generated field mask directly to the update call.

// Update campaign by setting its status to paused, and "Search network" to false.
Campaign campaignToUpdate = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
    Status = CampaignStatus.Paused,
    NetworkSettings = new NetworkSettings()
    {
        TargetSearchNetwork = false
    }
};

// Create the operation.
CampaignOperation operation = new CampaignOperation()
{
    Update = campaignToUpdate,
    UpdateMask = FieldMasks.AllSetFieldsOf(campaignToUpdate)
};

// Update the campaign.
MutateCampaignsResponse response = campaignService.MutateCampaigns(
    customerId.ToString(), new CampaignOperation[] { operation });

Sometimes, you may need to work with an existing object, and update a few fields. In such cases, you'd modify the code to use the FieldMasks.FromChanges method instead. This method generates a field mask that represents the difference between two objects.

Campaign existingCampaign;

// Obtain existingCampaign from elsewhere.
...

// Create a new campaign based off the existing campaign for update.
Campaign campaignToUpdate = new Campaign(existingCampaign);

// Update campaign by setting its status to paused, and "Search network" to
// false.
campaignToUpdate.Status = CampaignStatus.Paused;
campaignToUpdate.NetworkSettings = new NetworkSettings()
{
    TargetSearchNetwork = false
}

// Create the operation.
CampaignOperation operation = new CampaignOperation()
{
    Update = campaignToUpdate,
    UpdateMask = FieldMasks.FromChanges(existingCampaign, campaignToUpdate)
};

How to handle FieldMaskError.FIELD_HAS_SUBFIELDS errors

On rare occasions, you may need to set a field without updating any of the sub-fields of that type. Consider the following example:

// Creates a campaign with the proper resource name and an empty
// MaximizeConversions field.
Campaign campaign = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
    MaximizeConversions = new MaximizeConversions()
};

CampaignOperation operation = new CampaignOperation()
{
    Update = campaign,
    UpdateMask = FieldMasks.AllSetFieldsOf(campaign)
};

MutateCampaignsResponse response = campaignService.MutateCampaigns(
    customerId.ToString(), new CampaignOperation[] { operation });

This API call will fail with an FieldMaskError.FIELD_HAS_SUBFIELDS error. Since MaximizeConversions has three sub-fields, the Google Ads API server expects field masks for those fields to be present in the request. However, FieldMaskUtil cannot generate field masks correctly in this situation, since the request is not setting these fields.

In such cases, you can manually edit the field mask as follows:

// Creates a Campaign object with the proper resource name.
Campaign campaign = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
};

FieldMask fieldMask = FieldMasks.AllSetFieldsOf(campaign);
// Only include 'maximize_conversions.target_cpa_micros' in the field mask
// as it is the only mutable subfield on MaximizeConversions when used as a
// standard bidding strategy.
//
// Learn more about standard and portfolio bidding strategies here:
// https://developers.google.com/google-ads/api/docs/campaigns/bidding/assign-strategies
fieldMask.Paths.AddRange(new string[] {
    "maximize_conversions.target_cpa_micros",
});

// Creates an operation to update the campaign with the specified fields.
CampaignOperation operation = new CampaignOperation()
{
    Update = campaign,
    UpdateMask = fieldMask
};

How to clear fields

Google Ads API supports clearing some field values. To clear a field, you must manually set the field mask for that field. Setting a field to its default value (such as zero for an int64 field) won't clear the field.

The following code example shows how to clear the target_cpa_micros field of MaximizeConversions bidding strategy.

Correct code

The following code clears the target_cpa_micros field because we are setting the maximize_conversions.target_cpa_micros in the field mask and not setting thecampaign.MaximizeConversions.TargetCpaMicros field.

// Creates a Campaign object with the proper resource name.
Campaign campaign = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
};

// Constructs a field mask from the existing campaign and adds the
// 'maximize_conversions.target_cpa_micros' field to the field mask, which will
// clear this field from the bidding strategy without impacting any other fields
// on the bidding strategy.
FieldMask fieldMask = FieldMasks.AllSetFieldsOf(campaign);
fieldMask.Paths.AddRange(new string[] {
    "maximize_conversions.target_cpa_micros",
});

// Creates an operation to update the campaign with the specified field.
CampaignOperation operation = new CampaignOperation()
{
    Update = campaign,
    UpdateMask = fieldMask
};

Incorrect code

The following code doesn't clear the target_cpa_micros field, since we are setting this field to zero. Both the FieldMaskUtils and the Google Ads API server will ignore this value. In addition, you may also not receive an error in this case, since the value was ignored by the server.

// Creates a campaign with the proper resource name and a MaximizeConversions
// object. Attempt to clear the target_cpa_micros field by setting it to 0.
Campaign campaign = new Campaign()
{
    ResourceName = ResourceNames.Campaign(customerId, campaignId),
    MaximizeConversions = new MaximizeConversions()
    {
        TargetCpaMicros = 0
    }
};

// Constructs an operation, using the FieldMasks' AllSetFieldsOf utility to
// derive the update mask. However, the field mask will NOT include
// 'maximize_conversions.target_cpa_micros'.
CampaignOperation operation = new CampaignOperation()
{
    Update = campaign,
    UpdateMask = FieldMasks.AllSetFieldsOf(campaign)
};

// Sends the operation in a mutate request that will succeed but will NOT update
// the 'target_cpa_micros' field because 'maximize_conversions.target_cpa_micros'
// was not included in the field mask.
MutateCampaignsResponse response = campaignService.MutateCampaigns(
    customerId.ToString(), new CampaignOperation[] { operation });