late-sdk 0.0.932 → 0.0.934
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/AdCampaignsApi.md +4 -4
- data/docs/CreateStandaloneAd200ResponseResultsInner.md +1 -1
- data/docs/CreateStandaloneAdRequest.md +2 -2
- data/docs/GetCampaignTargeting200ResponseDevicesInner.md +1 -1
- data/docs/PlatformTarget.md +1 -1
- data/docs/UpdateAdRequestTargeting.md +1 -1
- data/docs/UpdateAdRequestTargetingDevicesInnerOneOf.md +1 -1
- data/lib/zernio-sdk/api/ad_campaigns_api.rb +8 -8
- data/lib/zernio-sdk/models/create_standalone_ad200_response_results_inner.rb +1 -1
- data/lib/zernio-sdk/models/create_standalone_ad_request.rb +2 -2
- data/lib/zernio-sdk/models/get_campaign_targeting200_response_devices_inner.rb +1 -1
- data/lib/zernio-sdk/models/platform_target.rb +1 -1
- data/lib/zernio-sdk/models/update_ad_request_targeting.rb +1 -1
- data/lib/zernio-sdk/models/update_ad_request_targeting_devices_inner_one_of.rb +6 -6
- data/lib/zernio-sdk/version.rb +1 -1
- data/openapi.yaml +26 -12
- data/spec/api/ad_campaigns_api_spec.rb +4 -4
- data/zernio-sdk-0.0.934.gem +0 -0
- metadata +2 -2
- data/zernio-sdk-0.0.932.gem +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2fdd09e1b2419a79142772fad8b249c5637ee4223dffdb2261025e5426c500e8
|
|
4
|
+
data.tar.gz: a4638ab5d0a53a0d21b7d29f6fe4bedcc983da8bb7747785586c3c71884281c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6506336929b72bc640d10bfcadd894bc45a17abac5fb40ed53b1b8951144e2b2e8e7ea7c4e875ef95e89bf2353672dc53fc7c5631a830fe149543b7f4786df03
|
|
7
|
+
data.tar.gz: 3a913bef3c9d7ccf32d3ee253ab55e24aa210acbfd6901b7f356c1f6a3bd3d351bbe8684266de5ad2783fa6db78073903232f1767181bea70489f1c5fe63f4d8
|
data/docs/AdCampaignsApi.md
CHANGED
|
@@ -1537,7 +1537,7 @@ end
|
|
|
1537
1537
|
|
|
1538
1538
|
Read a Google campaign's device, location, and language targeting
|
|
1539
1539
|
|
|
1540
|
-
Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices`
|
|
1540
|
+
Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices` lists the device criteria the campaign carries, which depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV. `bidModifier` is Google's bid adjustment for that device, `null` when it has none, and `0` when the device is switched off; `included` is false for exactly that case.
|
|
1541
1541
|
|
|
1542
1542
|
### Examples
|
|
1543
1543
|
|
|
@@ -2769,7 +2769,7 @@ end
|
|
|
2769
2769
|
|
|
2770
2770
|
Update ad
|
|
2771
2771
|
|
|
2772
|
-
Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed); a kind left out is untouched.
|
|
2772
|
+
Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
|
|
2773
2773
|
|
|
2774
2774
|
### Examples
|
|
2775
2775
|
|
|
@@ -2911,7 +2911,7 @@ end
|
|
|
2911
2911
|
|
|
2912
2912
|
Pause or resume a campaign
|
|
2913
2913
|
|
|
2914
|
-
Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on.
|
|
2914
|
+
Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on. Google keeps an independent on/off switch at campaign, ad group and ad level and the most restrictive one wins, so `active` switches the campaign on TOGETHER with the ad groups and ads Zernio tracks under it, in one mutate. Without that the campaign reads ENABLED while a paused ad group or ad keeps it from serving. `paused` writes the campaign alone, which already stops delivery and leaves each ad's own switch as you set it.
|
|
2915
2915
|
|
|
2916
2916
|
### Examples
|
|
2917
2917
|
|
|
@@ -3479,7 +3479,7 @@ end
|
|
|
3479
3479
|
|
|
3480
3480
|
Edit a Google campaign's device, location, or language targeting
|
|
3481
3481
|
|
|
3482
|
-
Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
3482
|
+
Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `devices` is the full set of device bid modifiers: a supported device you leave out is switched off with a bid modifier of 0, since Google cannot remove a device criterion. A device the campaign's channel does not carry, and a set that switches every device off, both return 422. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
3483
3483
|
|
|
3484
3484
|
### Examples
|
|
3485
3485
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **node** | **String** | | [optional] |
|
|
8
8
|
| **status** | **String** | | [optional] |
|
|
9
|
-
| **reason** | **String** | Why the node could not be validated (
|
|
9
|
+
| **reason** | **String** | Why the node could not be validated (on skipped), or what the dry run could not check and what the request would do as sent (on validated). A Performance Max validation with no location targeting reports here that the campaign would run worldwide. | [optional] |
|
|
10
10
|
|
|
11
11
|
## Example
|
|
12
12
|
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
| **validate_only** | **Boolean** | Google Performance Max validates the complete atomic campaign and asset group with no resource creation or local persistence. Google validation still downloads image URLs and consumes quota. On Meta, validates the complete inline campaign, ad set, creative and ad with execution_options validate_only. Nothing is uploaded or created, and validation bypasses Idempotency-Key storage. Supports a single image, all-image placementAssets with per-rule copy, existing video.id or existingCreativeId; other media pools, new video uploads, creatives[], adSetId and RESERVED buying return 400. Placement validation uses existing Instagram identities only. Existing campaign or creative nodes are marked skipped. Success returns 200 with per-node results; Meta rejection returns an error. | [optional] |
|
|
23
23
|
| **budget_amount** | **Float** | Budget in WHOLE currency units (USD: 50 = $50.00), NOT cents. Meta's own Marketing API takes this same number in minor units, so it is an easy and expensive mix-up. Required on legacy, multi-creative and Performance Max shapes. Inherited on attach. OpenAI Ads requires a $1 minimum (its budget is lifetime-only, see budgetType). | [optional] |
|
|
24
24
|
| **budget_type** | **String** | Required on legacy, multi-creative and Performance Max shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window. | [optional] |
|
|
25
|
-
| **status** | **String** | Google Performance Max accepts PAUSED only and always creates a paused campaign. Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each). | [optional] |
|
|
26
|
-
| **campaign_status** | **String** | Meta
|
|
25
|
+
| **status** | **String** | Google Performance Max accepts PAUSED only and always creates a paused campaign. Google Search and Display, Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. Google Search and Display follow the same rule, and because Google keeps an independent switch at campaign, ad group and ad level, a PAUSED create leaves the campaign it creates PAUSED at Google. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each). | [optional] |
|
|
26
|
+
| **campaign_status** | **String** | Meta and Google. Overrides `status` for the campaign level alone, so you can create a live campaign whose ad set and ad stay paused, or the reverse. Omitted, it follows `status`. | [optional] |
|
|
27
27
|
| **budget_level** | **String** | Meta only. Where the budget lives, which selects the Meta budget model: - `adset` (default): ABO (Ad-set Budget Optimization). The budget is set on the ad set. This is the back-compatible behaviour; omit this field to keep it. - `campaign`: CBO (Campaign Budget Optimization / Advantage Campaign Budget). The budget AND `bidStrategy` are set on the CAMPAIGN, and Meta distributes spend across ad sets automatically. The returned ad stores the applied `budgetLevel` and budget in `campaignBudget` for CBO or `adSetBudget` for ABO. Edit CBO budgets with `PUT /v1/ads/campaigns/{campaignId}` and ABO budgets with `PUT /v1/ads/ad-sets/{adSetId}`. Meta requires the budget at exactly one level, never both. Non-Meta platforms ignore this field. Ignored on the attach shape (`adSetId`), which inherits the existing budget. | [optional][default to 'adset'] |
|
|
28
28
|
| **currency** | **String** | ISO 4217 currency code matching the ad account's currency (e.g. `USD`). Meta only. Optional: Zernio resolves it from the ad account when omitted. The value selects the minor-unit exponent Zernio converts budget/bid amounts by before calling Meta (most currencies are cents; zero-decimal currencies like JPY/KRW are sent as-is). | [optional] |
|
|
29
29
|
| **headline** | **String** | Required for Meta, Google, Pinterest, LinkedIn, and OpenAI Ads on legacy + attach shapes (skip for multi-creative; use `creatives[].headline`). Ignored for TikTok and X. Max: Meta=255, Google=30, Pinterest=100, LinkedIn=400, OpenAI=50 (min 3). On LinkedIn this is the ad's headline (the bold text on the creative); for traffic ads it's the link card title. On OpenAI Ads this is the chat card's title. | [optional] |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **device** | **String** | | [optional] |
|
|
8
8
|
| **included** | **Boolean** | | [optional] |
|
|
9
|
-
| **bid_modifier** | **Float** |
|
|
9
|
+
| **bid_modifier** | **Float** | Google's bid adjustment for this device: null when it has none, 0 when the device is switched off, otherwise 0.1 to 10. | [optional] |
|
|
10
10
|
|
|
11
11
|
## Example
|
|
12
12
|
|
data/docs/PlatformTarget.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
| **is_trial_reel** | **Boolean** | Present and true only when this Instagram reel was launched as a Trial through Zernio (created with platformSpecificData.trialParams). Use it to segment trial reels in analytics. Note: Instagram's Graph API exposes no readable trial field, so this reflects creation-time intent only. It indicates the reel STARTED as a trial, not whether or when it graduated. | [optional] |
|
|
19
19
|
| **trial_graduation_strategy** | **String** | Graduation strategy the trial reel was launched with. Present only when isTrialReel is true. | [optional] |
|
|
20
20
|
| **error_message** | **String** | Human-readable error message when status is failed. Contains platform-specific error details explaining why the publish failed. | [optional] |
|
|
21
|
-
| **error_category** | **String** | Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (shared
|
|
21
|
+
| **error_category** | **String** | Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (a shared quota pool the integration draws on is empty, including our own capacity gate in front of one; not caused by your content or account, and safe to retry once the pool frees up), system_error (Zernio infra), unknown | [optional] |
|
|
22
22
|
| **error_source** | **String** | Who caused the error: user (fix content/reconnect), platform (outage/API change), system (Zernio issue, rare) | [optional] |
|
|
23
23
|
|
|
24
24
|
## Example
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **keywords** | [**Array<UpdateAdRequestTargetingKeywordsInner>**](UpdateAdRequestTargetingKeywordsInner.md) | Google only. The FULL desired set of positive keywords for the entire ad group. Omit to leave positives unchanged; [] removes all positives. Negatives are independent. Entries are strings (BROAD) or { text, matchType } with matchType exact | phrase | broad; an omitted matchType also defaults to BROAD. Matching case-insensitive text AND match type retains the existing criterion ID, status, bid overrides, labels and history without a mutation. A changed text or match type uses remove/create, without transferring the old criterion's attributes or history. See Google keyword replacement above for an EXACT-to-BROAD example. Mirrored to GET /v1/ads/keywords immediately. | [optional] |
|
|
8
8
|
| **negative_keywords** | [**Array<UpdateAdRequestTargetingKeywordsInner>**](UpdateAdRequestTargetingKeywordsInner.md) | Google only. The FULL desired set of negative keywords for the entire ad group, independent of positives. Omit to leave negatives unchanged; [] removes all negatives. Uses the same text/match-type identity and preservation contract as keywords above. Strings and objects without matchType default to BROAD, so resending an EXACT or PHRASE negative as a bare string requests a different criterion. Campaign negatives are separate: use /v1/ads/campaigns/{campaignId}/negative-keywords to manage those. | [optional] |
|
|
9
|
-
| **devices** | [**Array<UpdateAdRequestTargetingDevicesInner>**](UpdateAdRequestTargetingDevicesInner.md) | Google only. The FULL new set of device
|
|
9
|
+
| **devices** | [**Array<UpdateAdRequestTargetingDevicesInner>**](UpdateAdRequestTargetingDevicesInner.md) | Google only. The FULL new set of device bid modifiers for the campaign. Entries are a device name alone (targeted, bid modifier reset to 1) or { device, bidModifier }. A supported device you leave out is switched off, written as a bid modifier of 0. Google never removes a device criterion, so an excluded device reads back as bidModifier 0 rather than disappearing, and a set that switches every device off returns 422. Which devices a campaign carries depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV, and sending a device the campaign does not carry returns 422. | [optional] |
|
|
10
10
|
| **age_min** | **Integer** | | [optional] |
|
|
11
11
|
| **age_max** | **Integer** | | [optional] |
|
|
12
12
|
| **countries** | **Array<String>** | ISO 3166-1 alpha-2 codes. On Google this is the FULL new country set for the campaign (same contract as `locations`); on LinkedIn it replaces the campaign's geo criteria. | [optional] |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
| Name | Type | Description | Notes |
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **device** | **String** | | |
|
|
8
|
-
| **bid_modifier** | **Float** | Google device bid modifier
|
|
8
|
+
| **bid_modifier** | **Float** | Google device bid modifier. 0 switches the device off (minus 100%); otherwise 0.1 to 10 (minus 90% to plus 900%). Google rejects any value between 0 and 0.1. | [optional] |
|
|
9
9
|
|
|
10
10
|
## Example
|
|
11
11
|
|
|
@@ -1566,7 +1566,7 @@ module Zernio
|
|
|
1566
1566
|
end
|
|
1567
1567
|
|
|
1568
1568
|
# Read a Google campaign's device, location, and language targeting
|
|
1569
|
-
# Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices`
|
|
1569
|
+
# Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices` lists the device criteria the campaign carries, which depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV. `bidModifier` is Google's bid adjustment for that device, `null` when it has none, and `0` when the device is switched off; `included` is false for exactly that case.
|
|
1570
1570
|
# @param campaign_id [String] Google platform campaign ID
|
|
1571
1571
|
# @param [Hash] opts the optional parameters
|
|
1572
1572
|
# @option opts [String] :platform Disambiguates when the same campaignId string exists on more than one connected platform.
|
|
@@ -1577,7 +1577,7 @@ module Zernio
|
|
|
1577
1577
|
end
|
|
1578
1578
|
|
|
1579
1579
|
# Read a Google campaign's device, location, and language targeting
|
|
1580
|
-
# Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices`
|
|
1580
|
+
# Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices` lists the device criteria the campaign carries, which depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV. `bidModifier` is Google's bid adjustment for that device, `null` when it has none, and `0` when the device is switched off; `included` is false for exactly that case.
|
|
1581
1581
|
# @param campaign_id [String] Google platform campaign ID
|
|
1582
1582
|
# @param [Hash] opts the optional parameters
|
|
1583
1583
|
# @option opts [String] :platform Disambiguates when the same campaignId string exists on more than one connected platform.
|
|
@@ -2904,7 +2904,7 @@ module Zernio
|
|
|
2904
2904
|
end
|
|
2905
2905
|
|
|
2906
2906
|
# Update ad
|
|
2907
|
-
# Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed); a kind left out is untouched.
|
|
2907
|
+
# Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
|
|
2908
2908
|
# @param ad_id [String]
|
|
2909
2909
|
# @param update_ad_request [UpdateAdRequest]
|
|
2910
2910
|
# @param [Hash] opts the optional parameters
|
|
@@ -2915,7 +2915,7 @@ module Zernio
|
|
|
2915
2915
|
end
|
|
2916
2916
|
|
|
2917
2917
|
# Update ad
|
|
2918
|
-
# Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed); a kind left out is untouched.
|
|
2918
|
+
# Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
|
|
2919
2919
|
# @param ad_id [String]
|
|
2920
2920
|
# @param update_ad_request [UpdateAdRequest]
|
|
2921
2921
|
# @param [Hash] opts the optional parameters
|
|
@@ -3052,7 +3052,7 @@ module Zernio
|
|
|
3052
3052
|
end
|
|
3053
3053
|
|
|
3054
3054
|
# Pause or resume a campaign
|
|
3055
|
-
# Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on.
|
|
3055
|
+
# Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on. Google keeps an independent on/off switch at campaign, ad group and ad level and the most restrictive one wins, so `active` switches the campaign on TOGETHER with the ad groups and ads Zernio tracks under it, in one mutate. Without that the campaign reads ENABLED while a paused ad group or ad keeps it from serving. `paused` writes the campaign alone, which already stops delivery and leaves each ad's own switch as you set it.
|
|
3056
3056
|
# @param campaign_id [String] Platform campaign ID
|
|
3057
3057
|
# @param update_ad_campaign_status_request [UpdateAdCampaignStatusRequest]
|
|
3058
3058
|
# @param [Hash] opts the optional parameters
|
|
@@ -3063,7 +3063,7 @@ module Zernio
|
|
|
3063
3063
|
end
|
|
3064
3064
|
|
|
3065
3065
|
# Pause or resume a campaign
|
|
3066
|
-
# Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on.
|
|
3066
|
+
# Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on. Google keeps an independent on/off switch at campaign, ad group and ad level and the most restrictive one wins, so `active` switches the campaign on TOGETHER with the ad groups and ads Zernio tracks under it, in one mutate. Without that the campaign reads ENABLED while a paused ad group or ad keeps it from serving. `paused` writes the campaign alone, which already stops delivery and leaves each ad's own switch as you set it.
|
|
3067
3067
|
# @param campaign_id [String] Platform campaign ID
|
|
3068
3068
|
# @param update_ad_campaign_status_request [UpdateAdCampaignStatusRequest]
|
|
3069
3069
|
# @param [Hash] opts the optional parameters
|
|
@@ -3654,7 +3654,7 @@ module Zernio
|
|
|
3654
3654
|
end
|
|
3655
3655
|
|
|
3656
3656
|
# Edit a Google campaign's device, location, or language targeting
|
|
3657
|
-
# Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
3657
|
+
# Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `devices` is the full set of device bid modifiers: a supported device you leave out is switched off with a bid modifier of 0, since Google cannot remove a device criterion. A device the campaign's channel does not carry, and a set that switches every device off, both return 422. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
3658
3658
|
# @param campaign_id [String] Google platform campaign ID
|
|
3659
3659
|
# @param update_campaign_targeting_request [UpdateCampaignTargetingRequest]
|
|
3660
3660
|
# @param [Hash] opts the optional parameters
|
|
@@ -3665,7 +3665,7 @@ module Zernio
|
|
|
3665
3665
|
end
|
|
3666
3666
|
|
|
3667
3667
|
# Edit a Google campaign's device, location, or language targeting
|
|
3668
|
-
# Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
3668
|
+
# Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `devices` is the full set of device bid modifiers: a supported device you leave out is switched off with a bid modifier of 0, since Google cannot remove a device criterion. A device the campaign's channel does not carry, and a set that switches every device off, both return 422. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
3669
3669
|
# @param campaign_id [String] Google platform campaign ID
|
|
3670
3670
|
# @param update_campaign_targeting_request [UpdateCampaignTargetingRequest]
|
|
3671
3671
|
# @param [Hash] opts the optional parameters
|
|
@@ -19,7 +19,7 @@ module Zernio
|
|
|
19
19
|
|
|
20
20
|
attr_accessor :status
|
|
21
21
|
|
|
22
|
-
# Why the node could not be validated (
|
|
22
|
+
# Why the node could not be validated (on skipped), or what the dry run could not check and what the request would do as sent (on validated). A Performance Max validation with no location targeting reports here that the campaign would run worldwide.
|
|
23
23
|
attr_accessor :reason
|
|
24
24
|
|
|
25
25
|
class EnumAttributeValidator
|
|
@@ -65,10 +65,10 @@ module Zernio
|
|
|
65
65
|
# Required on legacy, multi-creative and Performance Max shapes. Inherited on attach. OpenAI Ads accepts lifetime only (no daily-budget concept on the platform); sending daily returns 422. OpenAI Ads lifetime budgets require `endDate` to give the lifetime cap a spend window.
|
|
66
66
|
attr_accessor :budget_type
|
|
67
67
|
|
|
68
|
-
# Google Performance Max accepts PAUSED only and always creates a paused campaign. Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).
|
|
68
|
+
# Google Performance Max accepts PAUSED only and always creates a paused campaign. Google Search and Display, Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. Google Search and Display follow the same rule, and because Google keeps an independent switch at campaign, ad group and ad level, a PAUSED create leaves the campaign it creates PAUSED at Google. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each).
|
|
69
69
|
attr_accessor :status
|
|
70
70
|
|
|
71
|
-
# Meta
|
|
71
|
+
# Meta and Google. Overrides `status` for the campaign level alone, so you can create a live campaign whose ad set and ad stay paused, or the reverse. Omitted, it follows `status`.
|
|
72
72
|
attr_accessor :campaign_status
|
|
73
73
|
|
|
74
74
|
# Meta only. Where the budget lives, which selects the Meta budget model: - `adset` (default): ABO (Ad-set Budget Optimization). The budget is set on the ad set. This is the back-compatible behaviour; omit this field to keep it. - `campaign`: CBO (Campaign Budget Optimization / Advantage Campaign Budget). The budget AND `bidStrategy` are set on the CAMPAIGN, and Meta distributes spend across ad sets automatically. The returned ad stores the applied `budgetLevel` and budget in `campaignBudget` for CBO or `adSetBudget` for ABO. Edit CBO budgets with `PUT /v1/ads/campaigns/{campaignId}` and ABO budgets with `PUT /v1/ads/ad-sets/{adSetId}`. Meta requires the budget at exactly one level, never both. Non-Meta platforms ignore this field. Ignored on the attach shape (`adSetId`), which inherits the existing budget.
|
|
@@ -19,7 +19,7 @@ module Zernio
|
|
|
19
19
|
|
|
20
20
|
attr_accessor :included
|
|
21
21
|
|
|
22
|
-
#
|
|
22
|
+
# Google's bid adjustment for this device: null when it has none, 0 when the device is switched off, otherwise 0.1 to 10.
|
|
23
23
|
attr_accessor :bid_modifier
|
|
24
24
|
|
|
25
25
|
class EnumAttributeValidator
|
|
@@ -55,7 +55,7 @@ module Zernio
|
|
|
55
55
|
# Human-readable error message when status is failed. Contains platform-specific error details explaining why the publish failed.
|
|
56
56
|
attr_accessor :error_message
|
|
57
57
|
|
|
58
|
-
# Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (shared
|
|
58
|
+
# Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (a shared quota pool the integration draws on is empty, including our own capacity gate in front of one; not caused by your content or account, and safe to retry once the pool frees up), system_error (Zernio infra), unknown
|
|
59
59
|
attr_accessor :error_category
|
|
60
60
|
|
|
61
61
|
# Who caused the error: user (fix content/reconnect), platform (outage/API change), system (Zernio issue, rare)
|
|
@@ -22,7 +22,7 @@ module Zernio
|
|
|
22
22
|
# Google only. The FULL desired set of negative keywords for the entire ad group, independent of positives. Omit to leave negatives unchanged; [] removes all negatives. Uses the same text/match-type identity and preservation contract as keywords above. Strings and objects without matchType default to BROAD, so resending an EXACT or PHRASE negative as a bare string requests a different criterion. Campaign negatives are separate: use /v1/ads/campaigns/{campaignId}/negative-keywords to manage those.
|
|
23
23
|
attr_accessor :negative_keywords
|
|
24
24
|
|
|
25
|
-
# Google only. The FULL new set of device
|
|
25
|
+
# Google only. The FULL new set of device bid modifiers for the campaign. Entries are a device name alone (targeted, bid modifier reset to 1) or { device, bidModifier }. A supported device you leave out is switched off, written as a bid modifier of 0. Google never removes a device criterion, so an excluded device reads back as bidModifier 0 rather than disappearing, and a set that switches every device off returns 422. Which devices a campaign carries depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV, and sending a device the campaign does not carry returns 422.
|
|
26
26
|
attr_accessor :devices
|
|
27
27
|
|
|
28
28
|
attr_accessor :age_min
|
|
@@ -17,7 +17,7 @@ module Zernio
|
|
|
17
17
|
class UpdateAdRequestTargetingDevicesInnerOneOf < ApiModelBase
|
|
18
18
|
attr_accessor :device
|
|
19
19
|
|
|
20
|
-
# Google device bid modifier
|
|
20
|
+
# Google device bid modifier. 0 switches the device off (minus 100%); otherwise 0.1 to 10 (minus 90% to plus 900%). Google rejects any value between 0 and 0.1.
|
|
21
21
|
attr_accessor :bid_modifier
|
|
22
22
|
|
|
23
23
|
class EnumAttributeValidator
|
|
@@ -114,8 +114,8 @@ module Zernio
|
|
|
114
114
|
invalid_properties.push('invalid value for "bid_modifier", must be smaller than or equal to 10.')
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
-
if !@bid_modifier.nil? && @bid_modifier < 0
|
|
118
|
-
invalid_properties.push('invalid value for "bid_modifier", must be greater than or equal to 0.
|
|
117
|
+
if !@bid_modifier.nil? && @bid_modifier < 0
|
|
118
|
+
invalid_properties.push('invalid value for "bid_modifier", must be greater than or equal to 0.')
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
invalid_properties
|
|
@@ -129,7 +129,7 @@ module Zernio
|
|
|
129
129
|
device_validator = EnumAttributeValidator.new('String', ["MOBILE", "DESKTOP", "TABLET", "CONNECTED_TV"])
|
|
130
130
|
return false unless device_validator.valid?(@device)
|
|
131
131
|
return false if !@bid_modifier.nil? && @bid_modifier > 10
|
|
132
|
-
return false if !@bid_modifier.nil? && @bid_modifier < 0
|
|
132
|
+
return false if !@bid_modifier.nil? && @bid_modifier < 0
|
|
133
133
|
true
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -154,8 +154,8 @@ module Zernio
|
|
|
154
154
|
fail ArgumentError, 'invalid value for "bid_modifier", must be smaller than or equal to 10.'
|
|
155
155
|
end
|
|
156
156
|
|
|
157
|
-
if bid_modifier < 0
|
|
158
|
-
fail ArgumentError, 'invalid value for "bid_modifier", must be greater than or equal to 0.
|
|
157
|
+
if bid_modifier < 0
|
|
158
|
+
fail ArgumentError, 'invalid value for "bid_modifier", must be greater than or equal to 0.'
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
@bid_modifier = bid_modifier
|
data/lib/zernio-sdk/version.rb
CHANGED
data/openapi.yaml
CHANGED
|
@@ -5455,7 +5455,7 @@ components:
|
|
|
5455
5455
|
errorCategory:
|
|
5456
5456
|
type: string
|
|
5457
5457
|
enum: [auth_expired, user_content, user_abuse, account_issue, platform_rejected, platform_error, platform_rate_limit, quota_exhausted, system_error, unknown]
|
|
5458
|
-
description: "Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (shared
|
|
5458
|
+
description: "Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (a shared quota pool the integration draws on is empty, including our own capacity gate in front of one; not caused by your content or account, and safe to retry once the pool frees up), system_error (Zernio infra), unknown"
|
|
5459
5459
|
errorSource:
|
|
5460
5460
|
type: string
|
|
5461
5461
|
enum: [user, platform, system]
|
|
@@ -43988,6 +43988,12 @@ paths:
|
|
|
43988
43988
|
|
|
43989
43989
|
On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with
|
|
43990
43990
|
PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on.
|
|
43991
|
+
|
|
43992
|
+
Google keeps an independent on/off switch at campaign, ad group and ad level and the most restrictive
|
|
43993
|
+
one wins, so `active` switches the campaign on TOGETHER with the ad groups and ads Zernio tracks under
|
|
43994
|
+
it, in one mutate. Without that the campaign reads ENABLED while a paused ad group or ad keeps it from
|
|
43995
|
+
serving. `paused` writes the campaign alone, which already stops delivery and leaves each ad's own
|
|
43996
|
+
switch as you set it.
|
|
43991
43997
|
security:
|
|
43992
43998
|
- bearerAuth: []
|
|
43993
43999
|
parameters:
|
|
@@ -44498,10 +44504,11 @@ paths:
|
|
|
44498
44504
|
(10 minutes fresh, up to 7 days last-good), not always a live read. Google
|
|
44499
44505
|
only; every other platform returns 501.
|
|
44500
44506
|
|
|
44501
|
-
`devices`
|
|
44502
|
-
|
|
44503
|
-
|
|
44504
|
-
|
|
44507
|
+
`devices` lists the device criteria the campaign carries, which depends on
|
|
44508
|
+
its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display
|
|
44509
|
+
campaigns also have CONNECTED_TV. `bidModifier` is Google's bid adjustment
|
|
44510
|
+
for that device, `null` when it has none, and `0` when the device is
|
|
44511
|
+
switched off; `included` is false for exactly that case.
|
|
44505
44512
|
security:
|
|
44506
44513
|
- bearerAuth: []
|
|
44507
44514
|
parameters:
|
|
@@ -44522,7 +44529,7 @@ paths:
|
|
|
44522
44529
|
properties:
|
|
44523
44530
|
device: { type: string, enum: [MOBILE, DESKTOP, TABLET, CONNECTED_TV] }
|
|
44524
44531
|
included: { type: boolean }
|
|
44525
|
-
bidModifier: { type: [number, "null"], description: "
|
|
44532
|
+
bidModifier: { type: [number, "null"], description: "Google's bid adjustment for this device: null when it has none, 0 when the device is switched off, otherwise 0.1 to 10." }
|
|
44526
44533
|
locations:
|
|
44527
44534
|
type: array
|
|
44528
44535
|
items:
|
|
@@ -44564,6 +44571,11 @@ paths:
|
|
|
44564
44571
|
out of the body are untouched. Google only; every other platform returns
|
|
44565
44572
|
501.
|
|
44566
44573
|
|
|
44574
|
+
`devices` is the full set of device bid modifiers: a supported device you
|
|
44575
|
+
leave out is switched off with a bid modifier of 0, since Google cannot
|
|
44576
|
+
remove a device criterion. A device the campaign's channel does not carry,
|
|
44577
|
+
and a set that switches every device off, both return 422.
|
|
44578
|
+
|
|
44567
44579
|
`locations` accepts the same shapes as campaign creation: a bare array of
|
|
44568
44580
|
ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros`
|
|
44569
44581
|
key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative
|
|
@@ -45423,7 +45435,9 @@ paths:
|
|
|
45423
45435
|
`targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE
|
|
45424
45436
|
edits via `targeting.languages`.
|
|
45425
45437
|
Each list you send becomes the FULL new set of its kind (criteria not in the
|
|
45426
|
-
list are removed
|
|
45438
|
+
list are removed, except devices, which Google cannot remove and which are
|
|
45439
|
+
switched off with a bid modifier of 0 instead); a kind left out is untouched.
|
|
45440
|
+
Any other `targeting` field
|
|
45427
45441
|
returns 400: Google cannot mutate it post-create without recreating
|
|
45428
45442
|
the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`,
|
|
45429
45443
|
and every supported field replaces a whole set; a field you omit is preserved.
|
|
@@ -45604,7 +45618,7 @@ paths:
|
|
|
45604
45618
|
- { type: object, required: [text], properties: { text: { type: string, maxLength: 80 }, matchType: { type: string, enum: [exact, phrase, broad] } } }
|
|
45605
45619
|
devices:
|
|
45606
45620
|
type: array
|
|
45607
|
-
description: "Google only. The FULL new set of device
|
|
45621
|
+
description: "Google only. The FULL new set of device bid modifiers for the campaign. Entries are a device name alone (targeted, bid modifier reset to 1) or { device, bidModifier }. A supported device you leave out is switched off, written as a bid modifier of 0. Google never removes a device criterion, so an excluded device reads back as bidModifier 0 rather than disappearing, and a set that switches every device off returns 422. Which devices a campaign carries depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV, and sending a device the campaign does not carry returns 422."
|
|
45608
45622
|
items:
|
|
45609
45623
|
oneOf:
|
|
45610
45624
|
- { type: string, enum: [MOBILE, DESKTOP, TABLET, CONNECTED_TV] }
|
|
@@ -45612,7 +45626,7 @@ paths:
|
|
|
45612
45626
|
required: [device]
|
|
45613
45627
|
properties:
|
|
45614
45628
|
device: { type: string, enum: [MOBILE, DESKTOP, TABLET, CONNECTED_TV] }
|
|
45615
|
-
bidModifier: { type: number, minimum: 0
|
|
45629
|
+
bidModifier: { type: number, minimum: 0, maximum: 10, description: 'Google device bid modifier. 0 switches the device off (minus 100%); otherwise 0.1 to 10 (minus 90% to plus 900%). Google rejects any value between 0 and 0.1.' }
|
|
45616
45630
|
ageMin: { type: integer, minimum: 13, maximum: 65 }
|
|
45617
45631
|
ageMax: { type: integer, minimum: 13, maximum: 65 }
|
|
45618
45632
|
countries: { type: array, items: { type: string }, description: "ISO 3166-1 alpha-2 codes. On Google this is the FULL new country set for the campaign (same contract as `locations`); on LinkedIn it replaces the campaign's geo criteria." }
|
|
@@ -51248,11 +51262,11 @@ paths:
|
|
|
51248
51262
|
status:
|
|
51249
51263
|
type: string
|
|
51250
51264
|
enum: [ACTIVE, PAUSED]
|
|
51251
|
-
description: "Google Performance Max accepts PAUSED only and always creates a paused campaign. Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each)."
|
|
51265
|
+
description: "Google Performance Max accepts PAUSED only and always creates a paused campaign. Google Search and Display, Meta, TikTok, and LinkedIn: publish state of the created entities. Omitted or ACTIVE publishes live (default, back-compat); PAUSED creates them paused so you can review before they spend. On Meta the pause is held on the campaign this call creates, leaving the ad set and ad switched on, so a single PUT /v1/ads/campaigns/{campaignId}/status with `active` brings the whole thing live. It is held at every level instead when the pause cannot rely on the campaign: `existingCampaignId` (that campaign may be running and is never touched) or `campaignStatus: ACTIVE`. Google Search and Display follow the same rule, and because Google keeps an independent switch at campaign, ad group and ad level, a PAUSED create leaves the campaign it creates PAUSED at Google. On TikTok the whole campaign > ad group > ad hierarchy stays paused. On LinkedIn the whole campaign group, campaign, and creative hierarchy stays PAUSED (intendedStatus PAUSED on each)."
|
|
51252
51266
|
campaignStatus:
|
|
51253
51267
|
type: string
|
|
51254
51268
|
enum: [ACTIVE, PAUSED]
|
|
51255
|
-
description: "Meta
|
|
51269
|
+
description: "Meta and Google. Overrides `status` for the campaign level alone, so you can create a live campaign whose ad set and ad stay paused, or the reverse. Omitted, it follows `status`."
|
|
51256
51270
|
budgetLevel:
|
|
51257
51271
|
type: string
|
|
51258
51272
|
enum: [adset, campaign]
|
|
@@ -52276,7 +52290,7 @@ paths:
|
|
|
52276
52290
|
properties:
|
|
52277
52291
|
node: { type: string, enum: [campaign, adSet, creative, ad, performanceMaxCampaign] }
|
|
52278
52292
|
status: { type: string, enum: [validated, skipped] }
|
|
52279
|
-
reason: { type: string, description: "Why the node could not be validated (
|
|
52293
|
+
reason: { type: string, description: "Why the node could not be validated (on skipped), or what the dry run could not check and what the request would do as sent (on validated). A Performance Max validation with no location targeting reports here that the campaign would run worldwide." }
|
|
52280
52294
|
message: { type: string }
|
|
52281
52295
|
'201':
|
|
52282
52296
|
description: Ad(s) created
|
|
@@ -312,7 +312,7 @@ describe 'AdCampaignsApi' do
|
|
|
312
312
|
|
|
313
313
|
# unit tests for get_campaign_targeting
|
|
314
314
|
# Read a Google campaign's device, location, and language targeting
|
|
315
|
-
# Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices`
|
|
315
|
+
# Google Ads compliance requires geo, language, budget, and bidding targeting set at creation to stay editable afterwards; this reads the campaign state so an integrator can build an editor around it. Cached for the quota window (10 minutes fresh, up to 7 days last-good), not always a live read. Google only; every other platform returns 501. `devices` lists the device criteria the campaign carries, which depends on its channel: Search campaigns have MOBILE, DESKTOP and TABLET, Display campaigns also have CONNECTED_TV. `bidModifier` is Google's bid adjustment for that device, `null` when it has none, and `0` when the device is switched off; `included` is false for exactly that case.
|
|
316
316
|
# @param campaign_id Google platform campaign ID
|
|
317
317
|
# @param [Hash] opts the optional parameters
|
|
318
318
|
# @option opts [String] :platform Disambiguates when the same campaignId string exists on more than one connected platform.
|
|
@@ -558,7 +558,7 @@ describe 'AdCampaignsApi' do
|
|
|
558
558
|
|
|
559
559
|
# unit tests for update_ad
|
|
560
560
|
# Update ad
|
|
561
|
-
# Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed); a kind left out is untouched.
|
|
561
|
+
# Patch one or more fields on an ad. Status, budget, targeting, and creative changes are propagated to the platform. Per-platform support: - **Meta** (Facebook + Instagram): all fields supported. - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`). - **Google**: status, budget, KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`, LOCATION edits via `targeting.locations` (or the equivalent top-level `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE edits via `targeting.languages`. Each list you send becomes the FULL new set of its kind (criteria not in the list are removed, except devices, which Google cannot remove and which are switched off with a bid modifier of 0 instead); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. Creative edits are dispatched on the ad's `advertisingChannelType`, and every supported field replaces a whole set; a field you omit is preserved. - **Search**: top-level `headlines`, `descriptions` and `finalUrls`. Use 3-15 headlines (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it; omit pinnedField on an included asset to unpin it. Updates do not pad or truncate text. The legacy creative fields remain unsupported. - **Display**: top-level `headlines` (1-5, no pinnedField, display ads have no pinned positions), `descriptions` (1-5) and `finalUrls`, plus `creative.longHeadline`, `creative.businessName`, `creative.imageUrl` (the landscape marketing image) and `creative.squareImageUrl`. Each image URL is uploaded as a new Google asset and the ad is pointed at it; Google assets are immutable, so the previous asset stays in the account's asset library. - **Performance Max**: top-level `assetGroup`, which swaps asset roles on the ad's asset group. The other creative fields return 422 for this channel, and `assetGroup` returns 422 on any other channel. - **LinkedIn**: status, budget, targeting (countries or regions, excludedLocations (countries), the B2B facets, and audience segments; applied to the LinkedIn Campaign via PARTIAL_UPDATE, and REPLACES the campaign's entire targetingCriteria, not a merge), and creative (uploads new media, creates a replacement inline creative on the same campaign, pauses the old one). - **Pinterest / X / OpenAI Ads**: status + budget only. Sending `targeting` or `creative` returns 501 with code `unsupported_platform_operation`. OpenAI Ads budget is lifetime-only (see `budget.type` below). **Google location and language replacement:** locations, languages and devices are campaign-level criteria on Google, so these edits apply to every ad group and ad in the ad's campaign. Send the complete list you want to keep. Zernio diffs it against the campaign's live criteria and sends the removes and the creates in ONE `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria already in the list keep their criterion ID and history. Excluded (negative) locations are left untouched. Two cases are refused rather than applied: an empty location list returns 400 (a Google campaign with no location criteria targets every country, which is never what \"remove my locations\" means, so omit the field instead), and radius targeting (`customLocations`) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either `targeting.locations` or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad's entire ad group, including sibling ads. Positive (`targeting.keywords`) and negative (`targeting.negativeKeywords`) sets are independent: omit a field to leave that set unchanged, or send `[]` to remove every keyword of that kind. Zernio compares each supplied set with Google's live criteria by case-insensitive keyword text and match type. A matching criterion is left untouched, retaining its criterion ID, enabled/paused status, keyword-level bid overrides, labels, and criterion-associated history/statistics. Zernio does not reset its quality score; Google continues to calculate scores and statistics normally. Text comparison does not trim whitespace. A bare string or an object without `matchType` means `broad`, not the existing criterion's match type. For example, resending an existing `{ \"text\": \"plumber\", \"matchType\": \"exact\" }` preserves it; sending `\"plumber\"` instead removes that EXACT criterion and requests a BROAD one. Changing text or match type removes criteria no longer requested and creates any missing criteria. New criteria get new IDs and do not inherit removed criteria's bid overrides, labels, or history. Historical reporting for a removed criterion is not transferred to its replacement. To add keywords without replacing a set, use [POST /v1/ads/keywords](https://docs.zernio.com/ad-campaigns/add-ad-keywords). Use `PATCH /v1/ads/keywords/{keywordId}` to pause/enable one keyword, or `DELETE /v1/ads/keywords/{keywordId}` to remove it.
|
|
562
562
|
# @param ad_id
|
|
563
563
|
# @param update_ad_request
|
|
564
564
|
# @param [Hash] opts the optional parameters
|
|
@@ -584,7 +584,7 @@ describe 'AdCampaignsApi' do
|
|
|
584
584
|
|
|
585
585
|
# unit tests for update_ad_campaign_status
|
|
586
586
|
# Pause or resume a campaign
|
|
587
|
-
# Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on.
|
|
587
|
+
# Writes the campaign's own on/off switch, then lets the platform cascade delivery to its ad sets and ads. Makes one platform API call, not one per ad. The switch is always written, whatever delivery status the ads underneath report: an ad still in review does not block resuming its campaign. The echoed `status` is the confirmation that it landed. `updated` / `skipped` describe only the ads whose own stored status CHANGED alongside it, so `updated: 0` is a normal successful response, not a no-op. Ads are skipped when they are in a terminal status (rejected, completed, cancelled), already in the target state, or switched on but not yet delivering. The last group keeps its `pending_review` / `error` status until the platform reports what it became. `skippedReasons` names which case applies. On Meta this flips the campaign only. An ad set paused in its own right stays paused, so pair this with PUT /v1/ads/ad-sets/{adSetId}/status when you also need the ad set switched back on. Google keeps an independent on/off switch at campaign, ad group and ad level and the most restrictive one wins, so `active` switches the campaign on TOGETHER with the ad groups and ads Zernio tracks under it, in one mutate. Without that the campaign reads ENABLED while a paused ad group or ad keeps it from serving. `paused` writes the campaign alone, which already stops delivery and leaves each ad's own switch as you set it.
|
|
588
588
|
# @param campaign_id Platform campaign ID
|
|
589
589
|
# @param update_ad_campaign_status_request
|
|
590
590
|
# @param [Hash] opts the optional parameters
|
|
@@ -688,7 +688,7 @@ describe 'AdCampaignsApi' do
|
|
|
688
688
|
|
|
689
689
|
# unit tests for update_campaign_targeting
|
|
690
690
|
# Edit a Google campaign's device, location, or language targeting
|
|
691
|
-
# Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
691
|
+
# Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of `devices`, `locations`, `languages`; each provided field REPLACES that field's existing criteria on the campaign (a full set, not a delta). Fields left out of the body are untouched. Google only; every other platform returns 501. `devices` is the full set of device bid modifiers: a supported device you leave out is switched off with a bid modifier of 0, since Google cannot remove a device criterion. A device the campaign's channel does not carry, and a set that switches every device off, both return 422. `locations` accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros` key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative (excluded) locations are left untouched by this endpoint. An empty location list returns 400 instead of removing every criterion: a Google campaign with no location criteria targets every country, so omit `locations` to leave targeting alone. The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed edit leaves the campaign's previous set intact rather than a half-applied one. `languages` is an array of Google's language codes (ISO 639-1, plus variants such as `zh_CN`); an unknown code returns 400. The response includes the refreshed `devices`/`locations`/`languages` state read back from Google after the edit, and invalidates the cached copy `GET` on this campaign would otherwise keep serving.
|
|
692
692
|
# @param campaign_id Google platform campaign ID
|
|
693
693
|
# @param update_campaign_targeting_request
|
|
694
694
|
# @param [Hash] opts the optional parameters
|
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: late-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.934
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenAPI-Generator
|
|
@@ -6367,7 +6367,7 @@ files:
|
|
|
6367
6367
|
- spec/models/you_tube_video_retention_response_retention_curve_inner_spec.rb
|
|
6368
6368
|
- spec/models/you_tube_video_retention_response_spec.rb
|
|
6369
6369
|
- spec/spec_helper.rb
|
|
6370
|
-
- zernio-sdk-0.0.
|
|
6370
|
+
- zernio-sdk-0.0.934.gem
|
|
6371
6371
|
- zernio-sdk.gemspec
|
|
6372
6372
|
homepage: https://openapi-generator.tech
|
|
6373
6373
|
licenses:
|
data/zernio-sdk-0.0.932.gem
DELETED
|
Binary file
|