Actualizaciones con máscaras de campo

En la API de Google Ads, las actualizaciones se realizan con una máscara de campo. La máscara de campo enumera todos los campos que deseas cambiar con la actualización, y se ignoran todos los campos especificados que no estén en la máscara de campo, incluso si se envían al servidor.

Asistente de máscara de campo

La forma recomendada de generar máscaras de campo es usar la función auxiliar field_mask incluida en el paquete google.api_core. Acepta dos objetos protobuf y devuelve un objeto de máscara de campo con una lista paths que contiene todos los campos que son diferentes entre los dos objetos.

Si se pasa None como primer parámetro, la lista de máscaras de campo contendrá todos los campos del segundo objeto .proto que no estén configurados en su valor predeterminado.

Una vez construido, el objeto de máscara de campo se debe copiar en el objeto de operación que se enviará al servidor.

Actualiza desde un objeto local nuevo

En el siguiente ejemplo, se crea un objeto CampaignOperation vacío y se recupera un objeto Campaign vacío de su campo update. Luego, modificas ese objeto de campaña y creas una nueva máscara de campo comparándolo con None, lo que genera una máscara de campo que contiene el campo network_settings.target_search_network modificado:

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)

Actualiza un recurso existente

En el siguiente ejemplo, se actualiza una campaña existente recuperada de la API, suponiendo que hay un resource_name y un customer_id válidos. Con esta estrategia, updated_campaign comparte todos los campos recuperados en initial_campaign (incluido su resource_name), y la máscara de campo generada le indica a la API que solo cambió el campo network_settings.target_search_network:

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)

Borrar campos o establecer mensajes vacíos

Cuando se compara con None, el asistente field_mask ignora los campos establecidos en valores vacíos o predeterminados. Para borrar un campo de forma explícita o establecer un campo de mensaje vacío, agrega la ruta del campo directamente a campaign_operation.update_mask.paths. Para obtener más detalles, consulta Cómo establecer objetos de mensajes vacíos como campos.