Aggiornamenti che utilizzano maschere di campo

Nell'API Google Ads, gli aggiornamenti vengono eseguiti utilizzando una maschera di campo. La maschera di campo elenca tutti i campi che intendi modificare con l'aggiornamento e tutti i campi specificati che non sono presenti nella maschera di campo vengono ignorati, anche se inviati al server.

FieldMaskUtil

Il modo consigliato per generare maschere di campo è utilizzare l'utilità di maschera di campo integrata, che nasconde dettagli specifici e ti consente di generare automaticamente maschere di campo monitorando le modifiche apportate ai campi dell'entità.

Il seguente esempio mostra come generare una maschera di campo per aggiornare una campagna:

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

Il codice crea innanzitutto un oggetto Campaign vuoto, quindi imposta il relativo nome risorsa per informare l'API della campagna da aggiornare.

Questo esempio utilizza il metodo client.field_mask.with nella campagna per iniziare il blocco che comprende gli aggiornamenti. Alla fine di questo blocco, l'utilità confronta lo stato attuale della campagna dopo il blocco con lo stato iniziale della campagna prima del blocco e genera automaticamente una maschera di campo che enumera i campi modificati. Puoi fornire la maschera di campo all'operazione quando la crei per la chiamata di mutazione come segue:

operation = client.operation.campaign
operation.update = campaign
operation.update_mask = mask

Questo metodo è consigliato quando crei un'operazione complessa e vuoi un controllo granulare su ogni passaggio. Tuttavia, nella maggior parte dei casi, puoi passare il nome della risorsa (o un'istanza di risorsa esistente) al metodo factory della libreria 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

Quando viene fornita una stringa del nome della risorsa, questo metodo crea automaticamente una nuova risorsa della campagna con resource_name compilato, crea la maschera di campo in base alle modifiche apportate all'interno del blocco, crea l'operazione di aggiornamento e restituisce l'operazione finale con update e update_mask già compilati. Puoi anche passare un'istanza proto Campaign esistente anziché una stringa del nome della risorsa per specificare lo stato iniziale della campagna. Questo pattern funziona per tutte le risorse che supportano l'operazione di aggiornamento.

Creare manualmente una maschera di campo

Per creare una maschera di campo da zero senza utilizzare le utilità della libreria, crea un Google::Protobuf::FieldMask, crea un array compilato con i nomi di tutti i campi che intendi modificare e assegna l'array al campo paths della maschera di campo:

mask = Google::Protobuf::FieldMask.new
mask.paths = ['status', 'name']

Aggiornare i campi dei messaggi e i relativi sottocampi

I campi MESSAGE possono avere sottocampi (ad esempio MaximizeConversions, che ne ha tre: target_cpa_micros, cpc_bid_ceiling_micros e cpc_bid_floor_micros) oppure non averne nessuno (ad esempio ManualCpm).

Campi dei messaggi senza sottocampi definiti

Quando aggiorni un campo MESSAGE non definito con sottocampi, utilizza FieldMaskUtil per generare una maschera di campo, come descritto in precedenza.

Campi dei messaggi con sottocampi definiti

Quando aggiorni un campo MESSAGE definito con sottocampi senza impostare esplicitamente nessuno dei sottocampi nel messaggio, devi aggiungere manualmente ciascuno dei sottocampi MESSAGE modificabili a FieldMask, in modo simile all'esempio precedente che ha creato una maschera di campo da zero.

Un esempio comune è l'aggiornamento della strategia di offerta di una campagna senza impostare nessuno dei campi della nuova strategia di offerta. Il seguente esempio mostra come aggiornare una campagna per utilizzare la strategia di offerta MaximizeConversions senza impostare nessuno dei sottocampi della strategia di offerta.

Per questo esempio, l'utilizzo del confronto integrato di FieldMaskUtil non raggiunge l'obiettivo previsto.

Il seguente codice genera una maschera di campo che include maximize_conversions. Tuttavia, l'API Google Ads non consente questo comportamento per evitare di cancellare accidentalmente i campi e genera un FieldMaskError.FIELD_HAS_SUBFIELDS errore.

# 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]
)

Cancellare i campi

Alcuni campi possono essere cancellati in modo esplicito. Analogamente all'esempio precedente, devi aggiungere esplicitamente questi campi alla maschera di campo. Ad esempio, supponiamo di avere una campagna che utilizza una strategia di offerta MaximizeConversions e che il campo target_cpa_micros sia impostato con un valore maggiore di 0.

In proto3, l'impostazione di un campo scalare non facoltativo sul valore predefinito (0) non è distinguibile dal fatto che non sia impostato in una nuova istanza del messaggio. Di conseguenza, FieldMaskUtil aggiunge maximize_conversions alla maschera di campo anziché maximize_conversions.target_cpa_micros, il che causa un errore 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]
)

Tieni presente che l'approccio di confronto automatico funziona come previsto per i campi definiti come optional nell'API Google Ads buffer di protocollo. Poiché target_cpa_micros non è un campo optional in MaximizeConversions, è necessario aggiungere esplicitamente il percorso a update_mask.paths per cancellarlo.