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. Puedes crear una máscara de campo de forma manual. Para ello, crea un FieldMask (Google\Protobuf\FieldMask), crea un array con los nombres de todos los campos que deseas cambiar y, luego, asigna ese array al campo paths de la máscara de campo.
También puedes usar nuestra utilidad de máscara de campo integrada (FieldMasks), que oculta muchos de los detalles específicos y te permite generar máscaras de campo automáticamente inspeccionando los cambios que realizas en los campos de la entidad.
A continuación, se incluye un ejemplo para actualizar una campaña:
$campaign = new Campaign([
'resource_name' => ResourceNames::forCampaign($customerId, $campaignId),
'status' => CampaignStatusEnum\CampaignStatus::PAUSED
]);
$campaignOperation = new CampaignOperation();
$campaignOperation->setUpdate($campaign);
$campaignOperation->setUpdateMask(FieldMasks::allSetFieldsOf($campaign));
Este código primero crea un objeto Campaign y, luego, establece su nombre de recurso con ResourceNames para que la API sepa qué campaña se está actualizando. status también se establece en CampaignStatus::PAUSED.
Luego, el código crea un objeto CampaignOperation y establece la campaña creada anteriormente en él. Luego, usa FieldMasks::allSetFieldsOf() para crear una máscara de campo para la campaña enumerando todos los campos modificados. Por último, pasa la máscara devuelta al objeto de operación de la campaña.
Ten en cuenta que FieldMasks::allSetFieldsOf() es un método de conveniencia para FieldMasks::compare(). Compara el objeto que pasaste con un objeto vacío de la misma clase. Por ejemplo, en el código anterior, podrías haber usado FieldMasks::compare(new Campaign(), $campaign) en lugar de FieldMasks::allSetFieldsOf($campaign).
Actualiza los campos de mensajes y sus subcampos
Los campos MESSAGE pueden tener subcampos (como MaximizeConversions, que incluye subcampos como 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 FieldMasks para generar una máscara de campo, como se describió anteriormente.
Campos de mensajes con subcampos definidos
Cuando actualices un campo MESSAGE que se define con subcampos sin establecer explícitamente ninguno de los subcampos en ese mensaje, debes agregar manualmente cada uno de los subcampos MESSAGE mutables al 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 configurar ninguno de los campos de la nueva estrategia de ofertas. En el siguiente código, se muestra cómo actualizar una campaña para que use la estrategia de ofertas MaximizeConversions sin configurar ninguno de los subcampos en la estrategia de ofertas.
En este caso, usar los métodos allSetFieldsOf() y compare() de FieldMasks no logra el objetivo previsto.
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 que se borren campos por accidente y produce un error FieldMaskError.FIELD_HAS_SUBFIELDS.
// Creates a campaign with the proper resource name and an empty
// MaximizeConversions field.
$campaign = new Campaign([
'resource_name' => ResourceNames::forCampaign($customerId, $campaignId),
'maximize_conversions' => new MaximizeConversions()
]);
// Constructs an operation, using the FieldMasks' allSetFieldsOf utility to
// derive the update mask. The field mask includes 'maximize_conversions',
// which produces a FieldMaskError.FIELD_HAS_SUBFIELDS error.
$campaignOperation = new CampaignOperation();
$campaignOperation->setUpdate($campaign);
$campaignOperation->setUpdateMask(FieldMasks::allSetFieldsOf($campaign));
// 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.
$campaignServiceClient = $googleAdsClient->getCampaignServiceClient();
$response = $campaignServiceClient->mutateCampaigns(
MutateCampaignsRequest::build($customerId, [$campaignOperation])
);
En el siguiente código, se muestra cómo actualizar correctamente una campaña para usar la estrategia de ofertas MaximizeConversions sin configurar ninguno de sus subcampos.
// Creates a Campaign object with the proper resource name.
$campaign = new Campaign([
'resource_name' => ResourceNames::forCampaign($customerId, $campaignId)
]);
// Creates a field mask from the existing campaign and adds the mutable
// subfield on the MaximizeConversions bidding strategy to the field mask.
// Because this field is included in the field mask but excluded from the
// campaign object, the Google Ads API sets the campaign's bidding strategy
// to a MaximizeConversions object without any of its subfields set.
$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:
// https://developers.google.com/google-ads/api/docs/campaigns/bidding/assign-strategies
$fieldMask->getPaths()[] = 'maximize_conversions.target_cpa_micros';
// Creates an operation to update the campaign with the specified fields.
$campaignOperation = new CampaignOperation();
$campaignOperation->setUpdate($campaign);
$campaignOperation->setUpdateMask($fieldMask);
Borrar campos
Algunos campos se pueden borrar de forma explícita. De manera similar al ejemplo anterior, debes agregar estos campos de forma explícita a la máscara de campo, ya que FieldMasks ignora los campos escalares de Proto3 establecidos en sus valores predeterminados (como 0, false o ""). Por ejemplo, supongamos que tienes una campaña que utiliza una estrategia de ofertas MaximizeConversions y que el campo target_cpa_micros se establece con un valor superior a 0.
El siguiente código se ejecuta; sin embargo, maximize_conversions.target_cpa_micros no se agregará a la máscara de campo, por lo que no se realizarán cambios en el campo target_cpa_micros:
// Creates a campaign with the proper resource name and a MaximizeConversions
// object with target_cpa_micros set to 0.
$campaign = new Campaign([
'resource_name' => ResourceNames::forCampaign($customerId, $campaignId),
'maximize_conversions' => new MaximizeConversions([
'target_cpa_micros' => 0
]),
'status' => CampaignStatusEnum\CampaignStatus::PAUSED
]);
// Constructs an operation, using the FieldMasks' allSetFieldsOf utility to
// derive the update mask. However, the field mask does NOT include
// 'maximize_conversions.target_cpa_micros'.
$campaignOperation = new CampaignOperation();
$campaignOperation->setUpdate($campaign);
$campaignOperation->setUpdateMask(FieldMasks::allSetFieldsOf($campaign));
// Sends the operation in a mutate request that succeeds, but does NOT update
// the 'target_cpa_micros' field because
// 'maximize_conversions.target_cpa_micros' was not included in the field mask.
$campaignServiceClient = $googleAdsClient->getCampaignServiceClient();
$response = $campaignServiceClient->mutateCampaigns(
MutateCampaignsRequest::build($customerId, [$campaignOperation])
);
En el siguiente código, se muestra cómo borrar correctamente el campo target_cpa_micros en la estrategia de ofertas MaximizeConversions.
// Creates a Campaign object with the proper resource name.
$campaign = new Campaign([
'resource_name' => ResourceNames::forCampaign($customerId, $campaignId)
]);
// Constructs a field mask from the existing campaign and adds the
// 'maximize_conversions.target_cpa_micros' field to the field mask, which
// clears this field from the bidding strategy without impacting any other
// fields on the bidding strategy.
$fieldMask = FieldMasks::allSetFieldsOf($campaign);
$fieldMask->getPaths()[] = 'maximize_conversions.target_cpa_micros';
// Creates an operation to update the campaign with the specified field.
$campaignOperation = new CampaignOperation();
$campaignOperation->setUpdate($campaign);
$campaignOperation->setUpdateMask($fieldMask);
Ten en cuenta que establecer un valor predeterminado funciona según lo previsto para los campos que se definen como optional en los búferes de protocolo de la API de Google Ads. Sin embargo, como target_cpa_micros no es un campo optional, establecerlo en 0 sin agregar explícitamente la ruta de acceso a la máscara de campo no actualiza la estrategia de ofertas para borrar target_cpa_micros.