В API Google Ads обновления выполняются с помощью маски полей. В маске полей перечислены все поля, которые вы планируете изменить при обновлении. Любые указанные поля, не входящие в маску, игнорируются, даже если они отправлены на сервер.
FieldMaskUtil
Рекомендуемый способ создания масок полей — использование нашей встроенной утилиты создания масок полей, которая скрывает множество специфических деталей и позволяет автоматически создавать маски полей, отслеживая изменения, вносимые вами в поля сущности.
Вот как можно создать маску поля для обновления кампании:
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
Сначала код создает пустой объект Campaign, затем задает имя его ресурса, чтобы информировать API об обновлении кампании.
В этом примере метод client.field_mask.with
кампании используется для начала блока, включающего обновления. В конце этого блока утилита сравнивает текущий статус кампании после блока с начальным статусом кампании до блока и автоматически создаёт маску полей, перечисляющую изменённые поля. Вы можете указать эту маску полей при её создании для вызова mutate следующим образом:
operation = client.operation.campaign
operation.update = campaign
operation.update_mask = mask
Этот метод рекомендуется при выполнении сложной операции и необходимости точного контроля над каждым этапом. Однако в большинстве случаев можно использовать более простую утилиту из библиотеки Ruby:
operation = client.operation.update_resource.campaign do |c|
c.status = :PAUSED
c.network_settings = client.resource.network_settings do |ns|
ns.target_search_network = false
end
end
Этот метод автоматически создаёт новый пустой ресурс кампании, формирует маску поля на основе изменений, внесённых вами в блоке, формирует операцию обновления и возвращает финальную операцию с уже заполненными параметрами update
и update_mask
. Вы также можете передать кампанию методу campaign
, чтобы указать её начальное состояние. Этот шаблон работает для всех ресурсов, поддерживающих операцию обновления.
Создание маски вручную
Чтобы создать маску поля с нуля, не используя какие-либо библиотечные утилиты, сначала нужно создать Google::Protobuf::FieldMask
, затем создать массив, заполненный именами всех полей, которые вы собираетесь изменить, и, наконец, назначить массив полю path
маски поля.
mask = Google::Protobuf::FieldMask.new
mask.path = ["status", "name"]
Обновление полей сообщений и их подполей
Поля MESSAGE
могут иметь подполя (например, MaximizeConversions
, у которого их три: target_cpa_micros
, cpc_bid_ceiling_micros
и cpc_bid_floor_micros
), или они могут не иметь ни одного подполя (например, ManualCpm
).
Поля сообщения без определенных подполей
При обновлении поля MESSAGE
, для которого не определены какие-либо подполя, используйте FieldMaskUtil для создания маски поля, как было показано ранее.
Поля сообщений с определенными подполями
При обновлении поля MESSAGE
, которое определено с подполями, без явной установки каких-либо подполей в этом сообщении, необходимо вручную добавить каждое из изменяемых подполей MESSAGE
в FieldMask
, аналогично предыдущему примеру, в котором маска поля создавалась с нуля.
Одним из распространённых примеров является обновление стратегии назначения ставок кампании без настройки каких-либо полей в новой стратегии. В следующем примере показано, как обновить кампанию для использования стратегии назначения ставок MaximizeConversions
без настройки каких-либо подполей в стратегии назначения ставок.
В этом примере использование встроенного сравнения FieldMaskUtil не достигает поставленной цели.
Следующий код генерирует маску поля, включающую maximize_conversions
. Однако API Google Ads не допускает такого поведения, чтобы предотвратить случайную очистку полей, и выдаёт ошибку FieldMaskError.FIELD_HAS_SUBFIELDS
.
# 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 will result 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],
)
В следующем коде показано, как правильно обновить кампанию для использования стратегии назначения ставок MaximizeConversions
без настройки каких-либо ее подполей.
# Create the operation directly from the campaign's resource name. Don't do
# anything in the block so that the field mask is empty. You could modify other
# fields in this block, just not the message field that is intended to have a
# blank subfield. We'll add that below.
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],
)
Очистка полей
Некоторые поля можно явно очистить. Как и в предыдущем примере, необходимо явно добавить эти поля в маску поля. Например, предположим, что у вас есть кампания со стратегией назначения ставок MaximizeConversions
, и поле target_cpa_micros
установлено со значением больше 0
.
Следующий код выполняется; однако maximize_conversions.target_cpa_micros
не будет добавлен в маску поля, поэтому никакие изменения в поле target_cpa_micros
не вносятся:
# 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 will include 'maximize_conversions',
# but not 'maximize_conversions.target_cpa_micros', so it will result 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 will fail since field mask is incorrect.
response = client.service.campaign.mutate_campaigns(
customer_id: customer_id,
operations: [operation],
end
В следующем коде показано, как правильно очистить поле target_cpa_micros
в стратегии назначения ставок MaximizeConversions
.
# Create a campaign including the maximize conversions fields right away, since
# we're going to manually add them 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 may add a block here with
# other changes that will automatically get 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 will succeed since we specified the correct field mask.
response = client.service.campaign.mutate_campaigns(
customer_id: customer_id,
operations: [operation],
end
Обратите внимание, что «неправильный» код работает так, как задумано для полей, которые определены как optional
в protocol buffers
API Google Ads. Но поскольку поле target_cpa_micros
не является optional
, «неправильный» код не обновляет стратегию назначения ставок, очищая поле target_cpa
.