Page Summary
-
Google Ads API uses field masks for updates, listing fields to be changed.
-
The
field_maskhelper function ingoogle.api_coreis the recommended way to generate field masks. -
The
field_maskhelper can compare two protobuf objects or compare a protobuf object toNoneto generate the mask. -
The generated field mask object must be copied onto the operation object before sending to the server.
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 are 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 paths list 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 contains
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 sent to the server.
Update from a new local object
In the following example, you create an empty
CampaignOperation object and retrieve an
empty Campaign object from its update field. You
then modify that campaign object and create a new field mask by comparing it to
None, which generates a field mask containing the modified
network_settings.target_search_network field:
from google.ads.googleads.client import GoogleAdsClient
from google.api_core import protobuf_helpers
# 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 and set its resource
# name.
campaign = campaign_operation.update
campaign.resource_name = client.get_service("CampaignService").campaign_path(
customer_id, campaign_id
)
# Mutate the campaign (use direct attribute assignment in proto-plus).
campaign.network_settings.target_search_network = False
# Create a field mask using the updated campaign.
# The field_mask helper is compatible with raw protobuf message instances,
# which you can access using the ._pb attribute.
field_mask = protobuf_helpers.field_mask(None, campaign._pb)
# Copy the field_mask onto the operation's update_mask field.
client.copy_from(campaign_operation.update_mask, field_mask)
Update an existing resource
The following example updates an existing campaign retrieved from the API,
assuming a valid resource_name and customer_id. With this strategy,
updated_campaign shares all the fields retrieved on initial_campaign
(including its resource_name), and the generated field mask tells the API that
only the network_settings.target_search_network field changed:
from google.ads.googleads.client import GoogleAdsClient
from google.api_core import protobuf_helpers
# Retrieve a GoogleAdsClient instance.
client = GoogleAdsClient.load_from_storage()
# Retrieve an instance of the GoogleAdsService.
googleads_service = client.get_service("GoogleAdsService")
# Search query to retrieve the campaign. Quote string literals in GAQL.
query = f"""
SELECT
campaign.network_settings.target_search_network,
campaign.resource_name
FROM campaign
WHERE campaign.resource_name = '{resource_name}'"""
# Submit a query to retrieve a campaign instance.
response = googleads_service.search_stream(
customer_id=customer_id, query=query
)
# Iterate over results to retrieve the campaign.
initial_campaign = None
for batch in response:
for row in batch.results:
initial_campaign = row.campaign
break
if not initial_campaign:
raise ValueError(f"Campaign '{resource_name}' not found.")
# Create a new campaign operation.
campaign_operation = client.get_type("CampaignOperation")
# Set the copied campaign object to a variable for easy reference.
updated_campaign = campaign_operation.update
# Copy the retrieved campaign into the new campaign.
# client.copy_from works with both native protobuf messages and messages
# wrapped by the proto-plus library.
client.copy_from(updated_campaign, initial_campaign)
# Mutate the new campaign.
updated_campaign.network_settings.target_search_network = False
# Create a field mask by comparing initial and updated protobuf objects.
field_mask = protobuf_helpers.field_mask(
initial_campaign._pb, updated_campaign._pb
)
# Copy the field mask onto the operation's update_mask field.
# Note that the client's copy_from method works with both native messages
# and messages wrapped by proto-plus, including google.protobuf.field_mask_pb2.
client.copy_from(campaign_operation.update_mask, field_mask)
Clear fields or set empty messages
When comparing against None, the field_mask helper ignores fields set to
empty or default values. To explicitly clear a field or set an empty message
field, append the field path directly to campaign_operation.update_mask.paths.
For more details, see
Set empty message objects as fields.