Google Ads API is returning to beta status. Please read our blog post for more details.

Updates Using Field Masks

In the Google Ads API, updates are done using a field mask. The field mask lists all the fields you intend to change with the update, and any specified fields that are not in the field mask will be ignored, even if sent to the server.

Field mask helper

The recommended way to generate field masks is using the field_mask helper function included in the google.api_core package. It accepts two protobuf objects and returns a field mask object with a list field that contains all of the fields that are different between the two objects.

If None is passed as the first parameter then the field mask list will just contain all of the fields on the second protobuf object that are not set to their default value.

Once constructed the field mask object should be copied onto the operation object that will be send to the server:

Here's an example for updating a campaign:

from google.api_core import protobuf_helpers
from google.ads.google_ads.client import GoogleAdsClient

# Retrieve a GoogleAdsClient instance.
client = GoogleAdsClient.load_from_storage()
# Create a new campaign operation.
campaign_operation = client.get_type('CampaignOperation')
# Retrieve a new campaign object from its update field.
campaign = campaign_operation.update
# Mutate the campaign.
campaign.network_settings.target_search_network.value = False

# Create a field mask using the updated campaign.
field_mask = protobuf_helpers.field_mask(None, campaign)

# Copy the field_mask onto the operation's update_mask field.
campaign_operation.update_mask.CopyFrom(field_mask)

First, we create an empty CampaignOperation object. Then, we set retrieve an empty Campaign object from it. We then update that campaign object and create a new field mask, comparing it to None, which will generate a field mask list that only contains the network_settings.target_search_network field that was changed.

Here's an example updating an existing campaign. Here we assume the script has been provided a resource_name parameter that is a valid resource name for a campaign and a valid customer_id:

from google.api_core import protobuf_helpers
from google.ads.google_ads.client import GoogleAdsClient

# Retrieve a GoogleAdsClient instance.
client = GoogleAdsClient.load_from_storage()
# Retrieve an instance of the GoogleAdsService.
google_ads_service = client.get_service('GoogleAdsService')

# Search query to retrieve campaign.
query = ('SELECT '
         'campaign.network_settings.target_search_network, '
         'campaign.resource_name '
         'FROM campaign '
         'WHERE campaign.resource_name = {}'.format(resource_name))

# Submit a query to retrieve a campaign instance.
response = google_ads_service.search_stream(customer_id, query=query)

# Iterate over results to retrieve the campaign.
for batch in response:
    for row in batch.results:
        initial_campaign = row.campaign

# Create a new campaign operation.
campaign_operation = client.get_type('CampaignOperation')
# Copy the retrieved campaign onto the new campaign operation's update field.
campaign_operation.update.CopyFrom(initial_campaign)
# Set the copied campaign object to a variable for easy reference.
updated_campaign = campaign_operation.update
# Mutate the new campaign.
updated_campaign.network_settings.target_search_network.value = False

# Create a field mask using the updated campaign.
field_mask = protobuf_helpers.field_mask(initial_campaign, updated_campaign)

# Copy the field mask onto the operation's update_mask field.
campaign_operation.update_mask.CopyFrom(field_mask)

With this strategy the updated_campaign will shared all the same fields as the initial_campaign that was retrieved from the API, namely the resource name. The generated field mask will tell the API that only the network_settings.target_search_network field needs to be changed.