מסכות שדה

ב-Google Ads API, העדכונים מתבצעים באמצעות מסכת שדות. מסכת השדות (google.protobuf.FieldMask) מכילה רשימה של נתיבי שדות ב-snake_case שאתם מתכוונים לשנות באמצעות העדכון. המערכת מתעלמת מכל שדה שצוין ולא נמצא במסכת השדות, גם אם הוא נשלח לשרת.

כלי השירות FieldMasks

הדרך המומלצת ליצור מסכות שדות בספריית הלקוח של Java היא להשתמש במחלקת השירות המובנית FieldMasks, שמאפשרת ליצור מסכות שדות מאובייקט ששונה במקום ליצור אותן מאפס.

דוגמה לעדכון קמפיין:

// 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 updates 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));

בדוגמה הזו, קודם נוצרת ישות ריקה של Campaign builder ומוגדר שם המשאב שלה, כדי שה-API ידע איזה קמפיין מתעדכן.

לאחר מכן, הדוגמה קוראת ל-FieldMasks.allSetFieldsOf() בקמפיין כדי ליצור באופן אוטומטי מסכת שדות שמפרטת את כל השדות שהוגדרו. אפשר להעביר את המסכה שהוחזרה ישירות לקריאת העדכון.

אם אתם צריכים לעבוד עם אובייקט קיים ולעדכן כמה שדות, השתמשו ב-FieldMasks.compare() באופן הבא:

// Assumes existingCampaign was retrieved from a previous API call.

// Creates a new campaign based on 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 updates 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));

כדי ליצור מסכת שדות מאפס, יוצרים אובייקט build של FieldMask ומוסיפים את השם של כל שדה שרוצים לשנות ב-snake_case:

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

עדכון שדות של הודעות ושדות משנה שלהם

בשדות MESSAGE יכולים להיות שדות משנה (כמו MaximizeConversions, שכולל את target_cpa_micros, cpc_bid_ceiling_micros ו-cpc_bid_floor_micros), או שלא יהיו בהם שדות משנה (כמו ManualCpm).

שדות של הודעות בלי שדות משנה מוגדרים

כשמעדכנים שדה MESSAGE שלא מוגדרים בו שדות משנה, משתמשים בכלי FieldMasks כדי ליצור מסכת שדה, כמו שמתואר בקטע הקודם.

שדות של הודעות עם שדות משנה מוגדרים

כשמעדכנים שדה MESSAGE שהוגדרו לו שדות משנה בלי להגדיר במפורש אף אחד משדות המשנה בהודעה הזו, צריך להוסיף ידנית כל אחד משדות המשנה הניתנים לשינוי של MESSAGE ל-FieldMask, בדומה ליצירת מסכת שדה מאפס.

דוגמה נפוצה היא עדכון של שיטת הבידינג בקמפיין (השדה oneof ב-campaign_bidding_strategy) בלי להגדיר אף אחד מהשדות בשיטת הבידינג החדשה. בדוגמה הבאה מוסבר איך לעדכן קמפיין כדי להשתמש בשיטת הבידינג MaximizeConversions בלי להגדיר אף אחד משדות המשנה של שיטת הבידינג.

במקרה כזה, שימוש בשיטות allSetFieldsOf() ו-compare() של FieldMasks בלבד לא ישיג את המטרה הרצויה.

בדוגמה הבאה נוצרת מסכת שדה שכוללת את maximize_conversions. עם זאת, Google Ads API לא מאפשר נתיבי הודעות ברמה העליונה שיש להם שדות משנה במסכת עדכון (כדי למנוע ניקוי בטעות של שדות משנה) ומחזיר שגיאת 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 FieldMasks.allSetFieldsOf to derive the update
// mask. The field mask includes 'maximize_conversions', which produces 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 results in a
// FieldMaskError.FIELD_HAS_SUBFIELDS error because empty MESSAGE fields with
// subfields cannot be included directly in a field mask.
MutateCampaignsResponse response =
    campaignServiceClient.mutateCampaigns(
        customerId.toString(), Collections.singletonList(operation));

בדוגמה הבאה מוסבר איך לעדכן קמפיין בצורה נכונה כדי להשתמש בשיטת הבידינג MaximizeConversions בלי להגדיר אף אחד משדות המשנה שלה. מידע נוסף על הקצאה של שיטות בידינג רגילות וכוללות

// 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 campaign and adds the mutable subfield
// ('maximize_conversions.target_cpa_micros') on the MaximizeConversions
// bidding strategy to the field mask. Because this subfield is included in the
// field mask while excluded from the campaign object, the Google Ads API
// switches the campaign's bidding strategy oneof to MaximizeConversions with
// target_cpa_micros unset.
FieldMask fieldMask =
    FieldMasks.allSetFieldsOf(campaign).toBuilder()
        .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();

ניקוי השדות

אפשר לנקות שדות מסוימים באופן מפורש. בדומה לדוגמה הקודמת, צריך להוסיף את השדות האלה באופן מפורש למסכת השדות, אבל לא להגדיר אותם באובייקט ההודעה. לדוגמה, נניח שיש לכם קמפיין שמוגדרת בו שיטת הבידינג MaximizeConversions, והשדה target_cpa_micros מוגדר עם ערך שגדול מ-0.

הקוד הבא פועל, אבל maximize_conversions.target_cpa_micros לא יימחק כמו שצריך:

// Creates a campaign with the proper resource name and a MaximizeConversions
// object with target_cpa_micros set to 0L.
Campaign campaign =
    Campaign.newBuilder()
        .setResourceName(ResourceNames.campaign(customerId, campaignId))
        .setMaximizeConversions(
            MaximizeConversions.newBuilder().setTargetCpaMicros(0L).build())
        .setStatus(CampaignStatus.PAUSED)
        .build();

// Constructs an operation using FieldMasks.allSetFieldsOf to derive the
// update mask.
CampaignOperation operation =
    CampaignOperation.newBuilder()
        .setUpdate(campaign)
        .setUpdateMask(FieldMasks.allSetFieldsOf(campaign))
        .build();

// Sends the operation in a mutate request that does not clear the field
// cleanly.
MutateCampaignsResponse response =
    campaignServiceClient.mutateCampaigns(
        customerId.toString(), Collections.singletonList(operation));

בדוגמה הבאה אפשר לראות איך לנקות בצורה נכונה את השדה target_cpa_micros בשיטת הבידינג 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 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 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();