En la API de Google Ads, las actualizaciones se realizan con una máscara de campo. La máscara de campo muestra todos los campos que deseas cambiar con la actualización, y se ignoran los campos especificados que no están en la máscara de campo, incluso si se envían al servidor.
FieldMaskUtil
La forma recomendada de generar máscaras de campo es usar la utilidad de máscara de campo integrada, que oculta detalles específicos y te permite generar máscaras de campo automáticamente supervisando los cambios que realizas en los campos de la entidad.
En el siguiente ejemplo, se muestra cómo generar una máscara de campo para actualizar una campaña:
campaign = client.resource.campaign
campaign.resource_name = client.path.campaign(customer_id, campaign_id)
mask = client.field_mask.with campaign do
campaign.status = :PAUSED
campaign.network_settings = client.resource.network_settings do |ns|
ns.target_search_network = false
end
end
Primero, el código crea un objeto Campaign vacío y, luego, establece su nombre de recurso para informar a la API sobre la campaña que se actualizará.
En este ejemplo, se usa el método client.field_mask.with en la campaña para iniciar el bloque que abarca las actualizaciones. Al final de este bloque, la utilidad compara el estado actual de la campaña después del bloque con el estado inicial de la campaña antes del bloque y genera automáticamente una máscara de campo que enumera los campos modificados. Puedes proporcionar esa máscara de campo a la operación cuando la construyas para la llamada de mutación de la siguiente manera:
operation = client.operation.campaign
operation.update = campaign
operation.update_mask = mask
Se recomienda este método cuando compilas una operación compleja y deseas un control detallado sobre cada paso. Sin embargo, en la mayoría de los casos, puedes pasar el nombre del recurso (o una instancia de recurso existente) al método de fábrica de la biblioteca de Ruby:
campaign_resource_name = client.path.campaign(customer_id, campaign_id)
operation =
client.operation.update_resource.campaign(campaign_resource_name) do |c|
c.status = :PAUSED
c.network_settings = client.resource.network_settings do |ns|
ns.target_search_network = false
end
end
Cuando se le proporciona una cadena de nombre de recurso, este método crea automáticamente un nuevo
recurso de campaña con resource_name propagado, construye la máscara de campo
en función de los cambios que realices dentro del bloque, compila la operación de actualización y
muestra la operación final con update y update_mask ya propagados.
También puedes pasar una instancia de proto Campaign existente en lugar de una cadena de nombre de recurso para especificar el estado inicial de la campaña. Este patrón funciona para todos los recursos que admiten la operación de actualización.
Cómo crear una máscara de campo de forma manual
Para crear una máscara de campo desde cero sin usar utilidades de biblioteca, crea un Google::Protobuf::FieldMask, crea un array propagado con los nombres de todos los campos que deseas cambiar y asigna el array al campo paths de la máscara de campo:
mask = Google::Protobuf::FieldMask.new
mask.paths = ['status', 'name']
Cómo actualizar los campos de mensajes y sus subcampos
Los campos MESSAGE pueden tener subcampos (como
MaximizeConversions, que tiene tres:
target_cpa_micros, cpc_bid_ceiling_micros y cpc_bid_floor_micros) o
no tener ninguno (como ManualCpm).
Campos de mensajes sin subcampos definidos
Cuando actualices un campo MESSAGE que no esté definido con ningún subcampo, usa FieldMaskUtil para generar una máscara de campo, como se presentó anteriormente.
Campos de mensajes con subcampos definidos
Cuando actualices un campo MESSAGE que esté definido con subcampos sin establecer explícitamente ninguno de los subcampos en ese mensaje, debes agregar manualmente cada uno de los subcampos MESSAGE mutables a FieldMask, de manera similar al ejemplo anterior que creó una máscara de campo desde cero.
Un ejemplo común es actualizar la estrategia de ofertas de una campaña sin establecer ninguno de los campos en la nueva estrategia de ofertas. En el siguiente ejemplo, se muestra
cómo actualizar una campaña para usar la estrategia de ofertas
MaximizeConversions
sin establecer ninguno de los subcampos en la estrategia de ofertas.
En este ejemplo, el uso de la comparación integrada de FieldMaskUtil no logra el objetivo deseado.
El siguiente código genera una máscara de campo que incluye maximize_conversions.
Sin embargo, la API de Google Ads no permite este comportamiento para evitar
borrar campos accidentalmente y produce un
FieldMaskError.FIELD_HAS_SUBFIELDS error.
# Creates a campaign with the proper resource name.
campaign = client.resource.campaign do |c|
c.resource_name = client.path.campaign(customer_id, campaign_id)
end
# Update the maximize conversions field within the update block, so it's
# captured in the field mask.
operation = client.operation.update_resource.campaign(campaign) do |c|
c.maximize_conversions = client.resource.maximize_conversions
end
# Sends the operation in a mutate request that results in a
# FieldMaskError.FIELD_HAS_SUBFIELDS error because empty MESSAGE fields cannot
# be included in a field mask.
response = client.service.campaign.mutate_campaigns(
customer_id: customer_id,
operations: [operation]
)
# Create the operation directly from the campaign's resource name. Don't do
# anything in the block so that the field mask starts empty. You can modify
# other fields in this block, except the message field intended to have a
# blank subfield.
campaign_resource_name = client.path.campaign(customer_id, campaign_id)
operation = client.operation.update_resource.campaign(campaign_resource_name) {}
# Manually add the maximize conversions subfield to the field mask so the API
# knows to clear it.
operation.update_mask.paths << 'maximize_conversions.target_cpa_micros'
# This operation succeeds.
response = client.service.campaign.mutate_campaigns(
customer_id: customer_id,
operations: [operation]
)
Borrar campos
Algunos campos se pueden borrar de forma explícita. Al igual que en el ejemplo anterior, debes agregar estos campos de forma explícita a la máscara de campo. Por ejemplo, supongamos que tienes una campaña que usa una estrategia de ofertas MaximizeConversions y que el campo target_cpa_micros está establecido con un valor mayor que 0.
En proto3, establecer un campo escalar no opcional en su valor predeterminado (0) no se distingue de dejarlo sin configurar en una instancia de mensaje nueva. Como resultado,
FieldMaskUtil agrega maximize_conversions a la máscara de campo en lugar de
maximize_conversions.target_cpa_micros, lo que provoca un error
FieldMaskError.FIELD_HAS_SUBFIELDS.
# Create a campaign object representing the campaign you want to change.
campaign = client.resource.campaign do |c|
c.resource_name = client.path.campaign(customer_id, campaign_id)
end
# The field mask in this operation includes 'maximize_conversions',
# but not 'maximize_conversions.target_cpa_micros', so it results in an
# error.
operation = client.operation.update_resource.campaign(campaign) do |c|
c.maximize_conversions = client.resource.maximize_conversions do |mc|
mc.target_cpa_micros = 0
end
end
# Operation fails because the field mask is invalid.
response = client.service.campaign.mutate_campaigns(
customer_id: customer_id,
operations: [operation]
)
# Create a campaign including the maximize conversions fields right away, since
# they are manually added to the field mask.
campaign = client.resource.campaign do |c|
c.resource_name = client.path.campaign(customer_id, campaign_id)
c.maximize_conversions = client.resource.maximize_conversions do |mc|
mc.target_cpa_micros = 0
end
end
# Create the operation with an empty field mask. You can add a block here with
# other changes that are automatically added to the field mask.
operation = client.operation.update_resource.campaign(campaign) {}
# Add the field to the field mask so the API knows to clear it.
operation.update_mask.paths << 'maximize_conversions.target_cpa_micros'
# Operation succeeds because the correct field mask is specified.
response = client.service.campaign.mutate_campaigns(
customer_id: customer_id,
operations: [operation]
)
Ten en cuenta que el enfoque de comparación automática funciona según lo previsto para los campos definidos
como optional en los búferes de protocolo de la API de Google Ads . Dado que
target_cpa_micros no es un campo optional en
MaximizeConversions, es
necesario agregar explícitamente la ruta de acceso a update_mask.paths para borrarla.