Máscaras de campo

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

FieldMaskUtil

La forma recomendada de generar máscaras de campo es usar nuestra utilidad de máscara de campo integrada, que te permite generar máscaras de campo a partir de un objeto modificado en lugar de compilarlas desde cero.

A continuación, se muestra un ejemplo para actualizar una campaña:

// Creates a Campaign object with the proper resource name and any other changes.
Campaign campaign =
    Campaign.newBuilder()
        .setResourceName(ResourceNames.campaign(customerId, campaignId))
        .setStatus(CampaignStatus.PAUSED)
        .build();

// Constructs an operation that will update the campaign, using the FieldMasks'
// allSetFieldsOf utility to derive the update mask. This mask tells the Google
// Ads API which attributes of the campaign you want to change.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaign)
        .setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
        .build();

// Sends the operation in a mutate request.
MutateCampaignsResponse response =
    campaignServiceClient.mutateCampaigns(
        customerId.toString(), Collections.singletonList(operation));

En este ejemplo, primero se crea un objeto Campaign vacío y, luego, se establece su nombre de recurso para que la API sepa qué campaña se está actualizando.

En el ejemplo, se usa el método FieldMasks.allSetFieldsOf() en la campaña para generar automáticamente una máscara de campo que enumere todos los campos establecidos. Luego, puedes pasar la máscara que se muestra directamente a la llamada de actualización.

Si necesitas trabajar con un objeto existente para actualizar algunos campos, puedes modificar el código de la siguiente manera:

Campaign existingCampaign;

// Obtains existingCampaign from elsewhere.
...

// Creates a new campaign based off the existing campaign and updates the
// campaign by setting its status to paused.
Campaign campaignToUpdate =
    existingCampaign.toBuilder()
        .setStatus(CampaignStatus.PAUSED)
        .build();

// Constructs an operation that will update the campaign, using the FieldMasks'
// compare utility to derive the update mask. This mask tells the Google Ads API
// which attributes of the campaign you want to change.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaignToUpdate)
        .setUpdateMask(FieldMasks.compare(existingCampaign, campaignToUpdate))
        .build();

// Sends the operation in a mutate request.
MutateCampaignsResponse response =
    campaignServiceClient.mutateCampaigns(
        customerId.toString(), Collections.singletonList(operation));

Para crear una máscara de campo desde cero, primero debes crear un objeto FieldMask y, luego, agregar el nombre de cada uno de los campos que deseas cambiar al objeto.

FieldMask fieldMask =
    FieldMask.newBuilder()
        .addPaths("status")
        .addPaths("name")
        .build();

Actualiza 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 describió anteriormente.

Campos de mensajes con subcampos definidos

Cuando actualizas un campo MESSAGE que se define con subcampos sin configurar 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 crea 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 ejemplo, se muestra cómo actualizar una campaña para que use la estrategia de ofertas MaximizeConversions sin configurar ninguno de los subcampos de la estrategia de ofertas.

En este caso, usar los métodos allSetFieldsOf() y compare() de FieldMaskUtil no logra el objetivo previsto.

En el siguiente ejemplo, se genera una máscara de campo que incluye maximize_conversions. Sin embargo, la API de Google Ads no permite que este comportamiento impida borrar campos por accidente y genera un error FieldMaskError.FIELD_HAS_SUBFIELDS.

// Creates a campaign with the proper resource name and an empty
// MaximizeConversions field.
Campaign campaign = Campaign.newBuilder()
    .setResourceName(ResourceNames.campaign(customerId, campaignId))
    .setMaximizeConversions(MaximizeConversions.newBuilder().build())
    .build();

// Constructs an operation, using the FieldMasks' allSetFieldsOf utility to
// derive the update mask. The field mask will include 'maximize_conversions`,
// which will produce a FieldMaskError.FIELD_HAS_SUBFIELDS error.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaign)
        .setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
        .build();

// Sends the operation in a mutate request that will result in a
// FieldMaskError.FIELD_HAS_SUBFIELDS error because empty MESSAGE fields cannot
// be included in a field mask.
MutateCampaignsResponse response =
    campaignServiceClient.mutateCampaigns(
        customerId.toString(), Collections.singletonList(operation));

En el siguiente ejemplo, 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 campaign = Campaign.newBuilder()
    .setResourceName(ResourceNames.campaign(customerId, campaignId))
    .build();

// Creates a field mask from the existing campaign and adds all of the mutable
// fields (only one in this case) 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 will set the campaign's
// bidding strategy to a MaximizeConversions object without any of its subfields
// set.
FieldMask fieldMask = FieldMasks.allSetFieldsOf(campaign)
    .toBuilder()
    // 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 here:
    // https://developers.google.com/google-ads/api/docs/campaigns/bidding/assign-strategies
    .addPaths("maximize_conversions.target_cpa_micros")
    .build();

// Creates an operation to update the campaign with the specified fields.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaign)
        .setUpdateMask(fieldMask)
        .build();

Cómo 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á configurado con un valor superior a 0.

Se ejecuta el siguiente código; 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 campaign =
    Campaign.newBuilder()
        .setResourceName(ResourceNames.campaign(customerId, campaignId))
        .setMaximizeConversions(
            MaximizeConversions.newBuilder().setTargetCpa(0).build())
        .setStatus(CampaignStatus.PAUSED)
        .build();

// Constructs an operation, using the FieldMasks' allSetFieldsOf utility to
// derive the update mask. However, the field mask will NOT include
// 'maximize_conversions.target_cpa_micros'.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaign)
        .setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
        .build();

// Sends the operation in a mutate request that will succeed but will NOT update
// the 'target_cpa_micros' field because
// 'maximize_conversions.target_cpa_micros' was not included in the field mask.
MutateCampaignsResponse response =
    campaignServiceClient.mutateCampaigns(
        customerId.toString(), Collections.singletonList(operation));

En el siguiente ejemplo, 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 campaign = Campaign.newBuilder()
    .setResourceName(ResourceNames.campaign(customerId, campaignId))
    .build();

// Constructs a field mask from the existing campaign and adds the
// 'maximize_conversions.target_cpa_micros' field to the field mask, which will
// clear this field from the bidding strategy without impacting any other fields
// on the bidding strategy.
FieldMask fieldMask = FieldMasks.allSetFieldsOf(campaign)
    .toBuilder()
    .addPaths("maximize_conversions.target_cpa_micros")
    .build();

// Creates an operation to update the campaign with the specified field.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaign)
        .setUpdateMask(fieldMask))
        .build();

Ten en cuenta que el ejemplo "incorrecto" anterior funciona según lo previsto para los campos que se definen como optional en la API de Google Ads protocol buffers. Sin embargo, como target_cpa_micros no es un campo optional, el ejemplo "incorrecto" no actualiza la estrategia de ofertas para borrar el campo target_cpa.