ב-Google Ads API, העדכונים מתבצעים באמצעות מסכת שדות. במסכת השדות מפורטים כל השדות שרוצים לשנות בעדכון, וכל השדות שצוינו שלא נמצאים במסכת השדות מתעלמים מהם, גם אם הם נשלחים לשרת.
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:
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
כשמעבירים למתודה הזו מחרוזת של שם משאב, היא יוצרת באופן אוטומטי משאב קמפיין חדש עם השדה resource_name מאוכלס, בונה את מסכת השדה על סמך השינויים שאתם מבצעים בבלוק, בונה את פעולת העדכון ומחזירה את הפעולה הסופית עם השדות update ו-update_mask שכבר מאוכלסים.
אפשר גם להעביר מופע קיים של Campaign proto במקום מחרוזת של שם משאב כדי לציין את מצב ההתחלה של הקמפיין. התבנית הזו מתאימה לכל המשאבים שתומכים בפעולת העדכון.
יצירה ידנית של מסכת שדות
כדי ליצור מסכת שדות מאפס בלי להשתמש בכלי עזר של ספרייה, יוצרים Google::Protobuf::FieldMask, יוצרים מערך עם השמות של כל השדות שרוצים לשנות, ומקצים את המערך לשדה paths של מסכת השדות:
mask = Google::Protobuf::FieldMask.new
mask.paths = ['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.
עם זאת, Google Ads API לא מאפשר התנהגות כזו כדי למנוע מחיקה מקרית של שדות, ומפיק שגיאה מסוג 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 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]
)
ניקוי השדות
אפשר לנקות חלק מהשדות באופן מפורש. בדומה לדוגמה הקודמת, צריך להוסיף את השדות האלה באופן מפורש למסכת השדות. לדוגמה, נניח שיש לכם קמפיין שמוגדרת בו שיטת בידינג מסוג MaximizeConversions, ושערך השדה target_cpa_micros גדול מ-0.
ב-proto3, אי אפשר להבחין בין הגדרה של שדה סקלרי לא אופציונלי לערך ברירת המחדל שלו (0) לבין השארת השדה ללא הגדרה במופע חדש של הודעה. כתוצאה מכך, FieldMaskUtil מוסיף את maximize_conversions למסכת השדות במקום את maximize_conversions.target_cpa_micros, וזה גורם לשגיאה 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]
)
שימו לב שהגישה של השוואה אוטומטית פועלת כמצופה בשדות שמוגדרים כ-optional במאגרי הפרוטוקולים של Google Ads API. מכיוון ש-target_cpa_micros הוא לא שדה optional ב-MaximizeConversions, צריך להוסיף את הנתיב ל-update_mask.paths באופן מפורש כדי לנקות אותו.