late-sdk 0.0.926 → 0.0.927

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43137fee183322363f1eb9958b2f1f7c52d3bc295a3af75204c3d809c990f0d1
4
- data.tar.gz: 972a1b1f952857c995325b1f9445b0546464719fdec007f0aa3a08e5f27a845a
3
+ metadata.gz: 3b522983a22f33b813eb3ed655ce02f772c4888899221e73b07b24a556691ba4
4
+ data.tar.gz: f9720e017147152e181119b0e9c29498ed99e1e476da7bc6bef6f6250b37434f
5
5
  SHA512:
6
- metadata.gz: 20b13b22d973d66981b40a9ec06fc45e7bd94579364e0d5f279ac8afe83ab45b338f36c8bf2b199d09ae28fc4405be74ed3f69a19017f04243710f32745cf56c
7
- data.tar.gz: 86b5cfd0a0b27d097c96a7fb0beb805d12f216ca64d98ebd186ad9fb4c2583603364c70354232a71ae810664f63583fc2d4ff0c44ca762d253a68af57f64b2c0
6
+ metadata.gz: 0ff6660bb98e1b02530c847c47d0a1c160f876078b329c4fd8f2935d33f4d9739ab812e9d2837c89cb93b1844502fcdc24034ef5586200626e58e0bf6d9c3dad
7
+ data.tar.gz: 9ae969e95899c088b1d390b415b3c86419d89d6d6fac8972ceddb495ca9e389f9a1ae1665f1731ef422cc96260aa7b73e413872980127809802ac1a1368b0bc5
data/README.md CHANGED
@@ -2452,6 +2452,7 @@ Class | Method | HTTP request | Description
2452
2452
  - [Zernio::UpdateAdRequestTargetingInterestsInner](docs/UpdateAdRequestTargetingInterestsInner.md)
2453
2453
  - [Zernio::UpdateAdRequestTargetingKeywordsInner](docs/UpdateAdRequestTargetingKeywordsInner.md)
2454
2454
  - [Zernio::UpdateAdRequestTargetingKeywordsInnerOneOf](docs/UpdateAdRequestTargetingKeywordsInnerOneOf.md)
2455
+ - [Zernio::UpdateAdRequestTargetingLocations](docs/UpdateAdRequestTargetingLocations.md)
2455
2456
  - [Zernio::UpdateAdSet200Response](docs/UpdateAdSet200Response.md)
2456
2457
  - [Zernio::UpdateAdSetRequest](docs/UpdateAdSetRequest.md)
2457
2458
  - [Zernio::UpdateAdSetRequestBudget](docs/UpdateAdSetRequestBudget.md)
@@ -2773,7 +2773,7 @@ end
2773
2773
 
2774
2774
  Update ad
2775
2775
 
2776
- 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`, and DEVICE bid adjustments via `targeting.devices`. 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. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. RSA text updates use top-level `headlines`, `descriptions` and `finalUrls`. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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 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.
2776
+ 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. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. RSA text updates use top-level `headlines`, `descriptions` and `finalUrls`. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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.
2777
2777
 
2778
2778
  ### Examples
2779
2779
 
@@ -3483,7 +3483,7 @@ end
3483
3483
 
3484
3484
  Edit a Google campaign's device, location, or language targeting
3485
3485
 
3486
- 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. `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.
3486
+ 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.
3487
3487
 
3488
3488
  ### Examples
3489
3489
 
@@ -9,7 +9,9 @@
9
9
  | **devices** | [**Array<UpdateAdRequestTargetingDevicesInner>**](UpdateAdRequestTargetingDevicesInner.md) | Google only. The FULL new set of device criteria for the campaign; devices not listed are excluded. Entries are a device name alone (included, no bid adjustment) or { device, bidModifier }. | [optional] |
10
10
  | **age_min** | **Integer** | | [optional] |
11
11
  | **age_max** | **Integer** | | [optional] |
12
- | **countries** | **Array<String>** | | [optional] |
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] |
13
+ | **locations** | [**UpdateAdRequestTargetingLocations**](UpdateAdRequestTargetingLocations.md) | | [optional] |
14
+ | **languages** | **Array<String>** | Google only. The FULL new language set for the campaign, as Google language codes (ISO 639-1, plus variants such as `zh_CN`). An unknown code returns 400. | [optional] |
13
15
  | **interests** | [**Array<UpdateAdRequestTargetingInterestsInner>**](UpdateAdRequestTargetingInterestsInner.md) | Interest objects from /v1/ads/interests. Each must include id and name. | [optional] |
14
16
  | **advantage_audience** | **Integer** | Meta only. Omit to preserve the existing setting on update. 0 = disabled, 1 = enabled. | [optional] |
15
17
 
@@ -25,6 +27,8 @@ instance = Zernio::UpdateAdRequestTargeting.new(
25
27
  age_min: null,
26
28
  age_max: null,
27
29
  countries: null,
30
+ locations: null,
31
+ languages: null,
28
32
  interests: null,
29
33
  advantage_audience: null
30
34
  )
@@ -0,0 +1,49 @@
1
+ # Zernio::UpdateAdRequestTargetingLocations
2
+
3
+ ## Class instance methods
4
+
5
+ ### `openapi_one_of`
6
+
7
+ Returns the list of classes defined in oneOf.
8
+
9
+ #### Example
10
+
11
+ ```ruby
12
+ require 'zernio-sdk'
13
+
14
+ Zernio::UpdateAdRequestTargetingLocations.openapi_one_of
15
+ # =>
16
+ # [
17
+ # :'Array<String>',
18
+ # :'UpdateCampaignTargetingRequestTargetingLocationsOneOf'
19
+ # ]
20
+ ```
21
+
22
+ ### build
23
+
24
+ Find the appropriate object from the `openapi_one_of` list and casts the data into it.
25
+
26
+ #### Example
27
+
28
+ ```ruby
29
+ require 'zernio-sdk'
30
+
31
+ Zernio::UpdateAdRequestTargetingLocations.build(data)
32
+ # => #<Array<String>:0x00007fdd4aab02a0>
33
+
34
+ Zernio::UpdateAdRequestTargetingLocations.build(data_that_doesnt_match)
35
+ # => nil
36
+ ```
37
+
38
+ #### Parameters
39
+
40
+ | Name | Type | Description |
41
+ | ---- | ---- | ----------- |
42
+ | **data** | **Mixed** | data to be matched against the list of oneOf items |
43
+
44
+ #### Return type
45
+
46
+ - `Array<String>`
47
+ - `UpdateCampaignTargetingRequestTargetingLocationsOneOf`
48
+ - `nil` (if no type matches)
49
+
@@ -2907,7 +2907,7 @@ module Zernio
2907
2907
  end
2908
2908
 
2909
2909
  # Update ad
2910
- # 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`, and DEVICE bid adjustments via `targeting.devices`. 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. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. RSA text updates use top-level `headlines`, `descriptions` and `finalUrls`. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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 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.
2910
+ # 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. Any other `targeting` field returns 400: Google cannot mutate it post-create without recreating the campaign. RSA text updates use top-level `headlines`, `descriptions` and `finalUrls`. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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.
2911
2911
  # @param ad_id [String]
2912
2912
  # @param update_ad_request [UpdateAdRequest]
2913
2913
  # @param [Hash] opts the optional parameters
@@ -2918,7 +2918,7 @@ module Zernio
2918
2918
  end
2919
2919
 
2920
2920
  # Update ad
2921
- # 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 &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style: &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Google**: status, budget, KEYWORD edits via &#x60;targeting.keywords&#x60; / &#x60;targeting.negativeKeywords&#x60;, and DEVICE bid adjustments via &#x60;targeting.devices&#x60;. 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. Any other &#x60;targeting&#x60; field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. RSA text updates use top-level &#x60;headlines&#x60;, &#x60;descriptions&#x60; and &#x60;finalUrls&#x60;. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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&#39;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 &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;. OpenAI Ads budget is lifetime-only (see &#x60;budget.type&#x60; below). **Google keyword replacement:** These edits affect the ad&#39;s entire ad group, including sibling ads. Positive (&#x60;targeting.keywords&#x60;) and negative (&#x60;targeting.negativeKeywords&#x60;) sets are independent: omit a field to leave that set unchanged, or send &#x60;[]&#x60; to remove every keyword of that kind. Zernio compares each supplied set with Google&#39;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 &#x60;matchType&#x60; means &#x60;broad&#x60;, not the existing criterion&#39;s match type. For example, resending an existing &#x60;{ \&quot;text\&quot;: \&quot;plumber\&quot;, \&quot;matchType\&quot;: \&quot;exact\&quot; }&#x60; preserves it; sending &#x60;\&quot;plumber\&quot;&#x60; 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&#39;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 &#x60;PATCH /v1/ads/keywords/{keywordId}&#x60; to pause/enable one keyword, or &#x60;DELETE /v1/ads/keywords/{keywordId}&#x60; to remove it.
2921
+ # 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 &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style: &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Google**: status, budget, KEYWORD edits via &#x60;targeting.keywords&#x60; / &#x60;targeting.negativeKeywords&#x60;, DEVICE bid adjustments via &#x60;targeting.devices&#x60;, LOCATION edits via &#x60;targeting.locations&#x60; (or the equivalent top-level &#x60;targeting.countries&#x60; / &#x60;regions&#x60; / &#x60;cities&#x60; / &#x60;zips&#x60; / &#x60;metros&#x60;), and LANGUAGE edits via &#x60;targeting.languages&#x60;. 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. Any other &#x60;targeting&#x60; field returns 400: Google cannot mutate it post-create without recreating the campaign. RSA text updates use top-level &#x60;headlines&#x60;, &#x60;descriptions&#x60; and &#x60;finalUrls&#x60;. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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&#39;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 &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;. OpenAI Ads budget is lifetime-only (see &#x60;budget.type&#x60; 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&#39;s campaign. Send the complete list you want to keep. Zernio diffs it against the campaign&#39;s live criteria and sends the removes and the creates in ONE &#x60;googleAds:mutate&#x60;, 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 \&quot;remove my locations\&quot; means, so omit the field instead), and radius targeting (&#x60;customLocations&#x60;) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either &#x60;targeting.locations&#x60; or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad&#39;s entire ad group, including sibling ads. Positive (&#x60;targeting.keywords&#x60;) and negative (&#x60;targeting.negativeKeywords&#x60;) sets are independent: omit a field to leave that set unchanged, or send &#x60;[]&#x60; to remove every keyword of that kind. Zernio compares each supplied set with Google&#39;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 &#x60;matchType&#x60; means &#x60;broad&#x60;, not the existing criterion&#39;s match type. For example, resending an existing &#x60;{ \&quot;text\&quot;: \&quot;plumber\&quot;, \&quot;matchType\&quot;: \&quot;exact\&quot; }&#x60; preserves it; sending &#x60;\&quot;plumber\&quot;&#x60; 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&#39;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 &#x60;PATCH /v1/ads/keywords/{keywordId}&#x60; to pause/enable one keyword, or &#x60;DELETE /v1/ads/keywords/{keywordId}&#x60; to remove it.
2922
2922
  # @param ad_id [String]
2923
2923
  # @param update_ad_request [UpdateAdRequest]
2924
2924
  # @param [Hash] opts the optional parameters
@@ -3657,7 +3657,7 @@ module Zernio
3657
3657
  end
3658
3658
 
3659
3659
  # Edit a Google campaign's device, location, or language targeting
3660
- # 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. `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.
3660
+ # 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.
3661
3661
  # @param campaign_id [String] Google platform campaign ID
3662
3662
  # @param update_campaign_targeting_request [UpdateCampaignTargetingRequest]
3663
3663
  # @param [Hash] opts the optional parameters
@@ -3668,7 +3668,7 @@ module Zernio
3668
3668
  end
3669
3669
 
3670
3670
  # Edit a Google campaign&#39;s device, location, or language targeting
3671
- # Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of &#x60;devices&#x60;, &#x60;locations&#x60;, &#x60;languages&#x60;; each provided field REPLACES that field&#39;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. &#x60;locations&#x60; accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with &#x60;countries&#x60;/&#x60;regions&#x60;/&#x60;cities&#x60;/&#x60;zips&#x60;/&#x60;metros&#x60; key lists (&#x60;key&#x60; from GET /v1/ads/targeting/search?dimension&#x3D;geo). Negative (excluded) locations are left untouched by this endpoint. &#x60;languages&#x60; is an array of Google&#39;s language codes (ISO 639-1, plus variants such as &#x60;zh_CN&#x60;); an unknown code returns 400. The response includes the refreshed &#x60;devices&#x60;/&#x60;locations&#x60;/&#x60;languages&#x60; state read back from Google after the edit, and invalidates the cached copy &#x60;GET&#x60; on this campaign would otherwise keep serving.
3671
+ # Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of &#x60;devices&#x60;, &#x60;locations&#x60;, &#x60;languages&#x60;; each provided field REPLACES that field&#39;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. &#x60;locations&#x60; accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with &#x60;countries&#x60;/&#x60;regions&#x60;/&#x60;cities&#x60;/&#x60;zips&#x60;/&#x60;metros&#x60; key lists (&#x60;key&#x60; from GET /v1/ads/targeting/search?dimension&#x3D;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 &#x60;locations&#x60; to leave targeting alone. The removes and the creates go out in ONE Google &#x60;googleAds:mutate&#x60;, so a failed edit leaves the campaign&#39;s previous set intact rather than a half-applied one. &#x60;languages&#x60; is an array of Google&#39;s language codes (ISO 639-1, plus variants such as &#x60;zh_CN&#x60;); an unknown code returns 400. The response includes the refreshed &#x60;devices&#x60;/&#x60;locations&#x60;/&#x60;languages&#x60; state read back from Google after the edit, and invalidates the cached copy &#x60;GET&#x60; on this campaign would otherwise keep serving.
3672
3672
  # @param campaign_id [String] Google platform campaign ID
3673
3673
  # @param update_campaign_targeting_request [UpdateCampaignTargetingRequest]
3674
3674
  # @param [Hash] opts the optional parameters
@@ -29,8 +29,14 @@ module Zernio
29
29
 
30
30
  attr_accessor :age_max
31
31
 
32
+ # 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.
32
33
  attr_accessor :countries
33
34
 
35
+ attr_accessor :locations
36
+
37
+ # Google only. The FULL new language set for the campaign, as Google language codes (ISO 639-1, plus variants such as `zh_CN`). An unknown code returns 400.
38
+ attr_accessor :languages
39
+
34
40
  # Interest objects from /v1/ads/interests. Each must include id and name.
35
41
  attr_accessor :interests
36
42
 
@@ -68,6 +74,8 @@ module Zernio
68
74
  :'age_min' => :'ageMin',
69
75
  :'age_max' => :'ageMax',
70
76
  :'countries' => :'countries',
77
+ :'locations' => :'locations',
78
+ :'languages' => :'languages',
71
79
  :'interests' => :'interests',
72
80
  :'advantage_audience' => :'advantage_audience'
73
81
  }
@@ -92,6 +100,8 @@ module Zernio
92
100
  :'age_min' => :'Integer',
93
101
  :'age_max' => :'Integer',
94
102
  :'countries' => :'Array<String>',
103
+ :'locations' => :'UpdateAdRequestTargetingLocations',
104
+ :'languages' => :'Array<String>',
95
105
  :'interests' => :'Array<UpdateAdRequestTargetingInterestsInner>',
96
106
  :'advantage_audience' => :'Integer'
97
107
  }
@@ -151,6 +161,16 @@ module Zernio
151
161
  end
152
162
  end
153
163
 
164
+ if attributes.key?(:'locations')
165
+ self.locations = attributes[:'locations']
166
+ end
167
+
168
+ if attributes.key?(:'languages')
169
+ if (value = attributes[:'languages']).is_a?(Array)
170
+ self.languages = value
171
+ end
172
+ end
173
+
154
174
  if attributes.key?(:'interests')
155
175
  if (value = attributes[:'interests']).is_a?(Array)
156
176
  self.interests = value
@@ -256,6 +276,8 @@ module Zernio
256
276
  age_min == o.age_min &&
257
277
  age_max == o.age_max &&
258
278
  countries == o.countries &&
279
+ locations == o.locations &&
280
+ languages == o.languages &&
259
281
  interests == o.interests &&
260
282
  advantage_audience == o.advantage_audience
261
283
  end
@@ -269,7 +291,7 @@ module Zernio
269
291
  # Calculates hash code according to all attributes.
270
292
  # @return [Integer] Hash code
271
293
  def hash
272
- [keywords, negative_keywords, devices, age_min, age_max, countries, interests, advantage_audience].hash
294
+ [keywords, negative_keywords, devices, age_min, age_max, countries, locations, languages, interests, advantage_audience].hash
273
295
  end
274
296
 
275
297
  # Builds the object from hash
@@ -0,0 +1,105 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'date'
14
+ require 'time'
15
+
16
+ module Zernio
17
+ # Google and LinkedIn. The FULL new location set for the campaign. Bare country-code array, or an object with countries/regions/cities/zips/metros key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Equivalent to the top-level geo fields; sending both returns 400. Empty returns 400, `customLocations` returns 422.
18
+ module UpdateAdRequestTargetingLocations
19
+ class << self
20
+ # List of class defined in oneOf (OpenAPI v3)
21
+ def openapi_one_of
22
+ [
23
+ :'Array<String>',
24
+ :'UpdateCampaignTargetingRequestTargetingLocationsOneOf'
25
+ ]
26
+ end
27
+
28
+ # Builds the object
29
+ # @param [Mixed] Data to be matched against the list of oneOf items
30
+ # @return [Object] Returns the model or the data itself
31
+ def build(data)
32
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
33
+ # Note:
34
+ # - We do not attempt to check whether exactly one item matches.
35
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
36
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
37
+ # - TODO: scalar values are de facto behaving as if they were nullable.
38
+ # - TODO: logging when debugging is set.
39
+ openapi_one_of.each do |klass|
40
+ begin
41
+ next if klass == :AnyType # "nullable: true"
42
+ return find_and_cast_into_type(klass, data)
43
+ rescue # rescue all errors so we keep iterating even if the current item lookup raises
44
+ end
45
+ end
46
+
47
+ openapi_one_of.include?(:AnyType) ? data : nil
48
+ end
49
+
50
+ private
51
+
52
+ SchemaMismatchError = Class.new(StandardError)
53
+
54
+ # Note: 'File' is missing here because in the regular case we get the data _after_ a call to JSON.parse.
55
+ def find_and_cast_into_type(klass, data)
56
+ return if data.nil?
57
+
58
+ case klass.to_s
59
+ when 'Boolean'
60
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
61
+ when 'Float'
62
+ return data if data.instance_of?(Float)
63
+ when 'Integer'
64
+ return data if data.instance_of?(Integer)
65
+ when 'Time'
66
+ return Time.parse(data)
67
+ when 'Date'
68
+ return Date.iso8601(data)
69
+ when 'String'
70
+ return data if data.instance_of?(String)
71
+ when 'Object' # "type: object"
72
+ return data if data.instance_of?(Hash)
73
+ when /\AArray<(?<sub_type>.+)>\z/ # "type: array"
74
+ if data.instance_of?(Array)
75
+ sub_type = Regexp.last_match[:sub_type]
76
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
77
+ end
78
+ when /\AHash<String, (?<sub_type>.+)>\z/ # "type: object" with "additionalProperties: { ... }"
79
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
80
+ sub_type = Regexp.last_match[:sub_type]
81
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
82
+ end
83
+ else # model
84
+ const = Zernio.const_get(klass)
85
+ if const
86
+ if const.respond_to?(:openapi_one_of) # nested oneOf model
87
+ model = const.build(data)
88
+ return model if model
89
+ else
90
+ # raise if data contains keys that are not known to the model
91
+ raise if const.respond_to?(:acceptable_attributes) && !(data.keys - const.acceptable_attributes).empty?
92
+ model = const.build_from_hash(data)
93
+ return model if model
94
+ end
95
+ end
96
+ end
97
+
98
+ raise # if no match by now, raise
99
+ rescue
100
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -11,5 +11,5 @@ Generator version: 7.19.0
11
11
  =end
12
12
 
13
13
  module Zernio
14
- VERSION = '0.0.926'
14
+ VERSION = '0.0.927'
15
15
  end
data/lib/zernio-sdk.rb CHANGED
@@ -1671,6 +1671,7 @@ require 'zernio-sdk/models/update_ad_request_targeting_devices_inner_one_of'
1671
1671
  require 'zernio-sdk/models/update_ad_request_targeting_interests_inner'
1672
1672
  require 'zernio-sdk/models/update_ad_request_targeting_keywords_inner'
1673
1673
  require 'zernio-sdk/models/update_ad_request_targeting_keywords_inner_one_of'
1674
+ require 'zernio-sdk/models/update_ad_request_targeting_locations'
1674
1675
  require 'zernio-sdk/models/update_ad_set200_response'
1675
1676
  require 'zernio-sdk/models/update_ad_set_request'
1676
1677
  require 'zernio-sdk/models/update_ad_set_request_budget'
data/openapi.yaml CHANGED
@@ -44452,7 +44452,12 @@ paths:
44452
44452
  `locations` accepts the same shapes as campaign creation: a bare array of
44453
44453
  ISO country codes, or an object with `countries`/`regions`/`cities`/`zips`/`metros`
44454
44454
  key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Negative
44455
- (excluded) locations are left untouched by this endpoint.
44455
+ (excluded) locations are left untouched by this endpoint. An empty location list
44456
+ returns 400 instead of removing every criterion: a Google campaign with no location
44457
+ criteria targets every country, so omit `locations` to leave targeting alone.
44458
+
44459
+ The removes and the creates go out in ONE Google `googleAds:mutate`, so a failed
44460
+ edit leaves the campaign's previous set intact rather than a half-applied one.
44456
44461
 
44457
44462
  `languages` is an array of Google's language codes (ISO 639-1, plus variants
44458
44463
  such as `zh_CN`); an unknown code returns 400.
@@ -45306,10 +45311,13 @@ paths:
45306
45311
  - **TikTok**: status, budget, targeting (via `/v2/adgroup/update/`), and creative
45307
45312
  (via `/v2/ad/update/` patch-style: `headline` is ignored, `body` becomes `ad_text`).
45308
45313
  - **Google**: status, budget, KEYWORD edits via `targeting.keywords` /
45309
- `targeting.negativeKeywords`, and DEVICE bid adjustments via `targeting.devices`.
45314
+ `targeting.negativeKeywords`, DEVICE bid adjustments via `targeting.devices`,
45315
+ LOCATION edits via `targeting.locations` (or the equivalent top-level
45316
+ `targeting.countries` / `regions` / `cities` / `zips` / `metros`), and LANGUAGE
45317
+ edits via `targeting.languages`.
45310
45318
  Each list you send becomes the FULL new set of its kind (criteria not in the
45311
45319
  list are removed); a kind left out is untouched. Any other `targeting` field
45312
- returns 400: Google cannot mutate broad targeting post-create without recreating
45320
+ returns 400: Google cannot mutate it post-create without recreating
45313
45321
  the campaign. RSA text updates use top-level `headlines`, `descriptions` and `finalUrls`.
45314
45322
  Each supplied array replaces the full list; omit a field to preserve it. Use 3-15 headlines
45315
45323
  (1-30 characters) and 2-4 descriptions (1-90 characters). Omit an asset to remove it;
@@ -45324,6 +45332,19 @@ paths:
45324
45332
  `targeting` or `creative` returns 501 with code `unsupported_platform_operation`.
45325
45333
  OpenAI Ads budget is lifetime-only (see `budget.type` below).
45326
45334
 
45335
+ **Google location and language replacement:** locations, languages and devices are
45336
+ campaign-level criteria on Google, so these edits apply to every ad group and ad in
45337
+ the ad's campaign. Send the complete list you want to keep. Zernio diffs it against
45338
+ the campaign's live criteria and sends the removes and the creates in ONE
45339
+ `googleAds:mutate`, so the campaign is never left with a half-applied set; criteria
45340
+ already in the list keep their criterion ID and history. Excluded (negative)
45341
+ locations are left untouched. Two cases are refused rather than applied: an empty
45342
+ location list returns 400 (a Google campaign with no location criteria targets every
45343
+ country, which is never what "remove my locations" means, so omit the field instead),
45344
+ and radius targeting (`customLocations`) returns 422 because it is a separate Google
45345
+ criterion type that this replacement neither creates nor removes. Send either
45346
+ `targeting.locations` or the top-level geo fields, not both: mixing them returns 400.
45347
+
45327
45348
  **Google keyword replacement:** These edits affect the ad's entire ad group,
45328
45349
  including sibling ads. Positive (`targeting.keywords`) and negative
45329
45350
  (`targeting.negativeKeywords`) sets are independent: omit a field to leave
@@ -45456,7 +45477,28 @@ paths:
45456
45477
  bidModifier: { type: number, minimum: 0.1, maximum: 10, description: 'Google device bid modifier, 0.1 to 10 (minus 90% to plus 900%). Omit a device to exclude it.' }
45457
45478
  ageMin: { type: integer, minimum: 13, maximum: 65 }
45458
45479
  ageMax: { type: integer, minimum: 13, maximum: 65 }
45459
- countries: { type: array, items: { type: string } }
45480
+ 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." }
45481
+ locations:
45482
+ description: "Google and LinkedIn. The FULL new location set for the campaign. Bare country-code array, or an object with countries/regions/cities/zips/metros key lists (`key` from GET /v1/ads/targeting/search?dimension=geo). Equivalent to the top-level geo fields; sending both returns 400. Empty returns 400, `customLocations` returns 422."
45483
+ oneOf:
45484
+ - type: array
45485
+ items: { type: string, description: "ISO 3166-1 alpha-2 country code." }
45486
+ - type: object
45487
+ properties:
45488
+ countries: { type: array, items: { type: string } }
45489
+ regions:
45490
+ type: array
45491
+ items: { type: object, required: [key], properties: { key: { type: string }, name: { type: string } } }
45492
+ cities:
45493
+ type: array
45494
+ items: { type: object, required: [key], properties: { key: { type: string }, name: { type: string } } }
45495
+ zips:
45496
+ type: array
45497
+ items: { type: object, required: [key], properties: { key: { type: string }, name: { type: string } } }
45498
+ metros:
45499
+ type: array
45500
+ items: { type: object, required: [key], properties: { key: { type: string }, name: { type: string } } }
45501
+ languages: { type: array, items: { type: string }, description: "Google only. The FULL new language set for the campaign, as Google language codes (ISO 639-1, plus variants such as `zh_CN`). An unknown code returns 400." }
45460
45502
  interests:
45461
45503
  type: array
45462
45504
  description: "Interest objects from /v1/ads/interests. Each must include id and name."
@@ -45520,11 +45562,12 @@ paths:
45520
45562
  ad: { $ref: '#/components/schemas/Ad' }
45521
45563
  message: { type: string }
45522
45564
  '400':
45523
- description: 'Invalid status transition, budget below minimum, a LinkedIn creative update without imageUrl or videoUrl, or a LinkedIn targeting update without countries or regions'
45565
+ description: 'Invalid status transition, budget below minimum, a LinkedIn creative update without imageUrl or videoUrl, a LinkedIn targeting update without countries or regions, or a Google targeting update that is unsupported, empty, mixes locations with the top-level geo fields, or names an unknown country or language code'
45524
45566
  '401': { $ref: '#/components/responses/Unauthorized' }
45525
45567
  '403':
45526
45568
  description: 'Returned with code `ads_allowance_exceeded` when the team has no payment method on file and has reached the 500 free live ads: add a card to resume.'
45527
45569
  '404': { $ref: '#/components/responses/NotFound' }
45570
+ '422': { description: "The ad has no campaign or ad group on the platform yet, or the Google targeting edit asks for something that is create-only (`locations.customLocations`)" }
45528
45571
  '501': { description: "targeting or creative not supported on the platform (supported on Meta, TikTok, and LinkedIn)" }
45529
45572
  '502': { description: "Meta accepted the request then failed to produce the media (upload session, chunk transfer, processing timeout, or a response with no image hash). Inspect `platformError.reason`." }
45530
45573
  delete:
@@ -559,7 +559,7 @@ describe 'AdCampaignsApi' do
559
559
 
560
560
  # unit tests for update_ad
561
561
  # Update ad
562
- # 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 &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style: &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Google**: status, budget, KEYWORD edits via &#x60;targeting.keywords&#x60; / &#x60;targeting.negativeKeywords&#x60;, and DEVICE bid adjustments via &#x60;targeting.devices&#x60;. 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. Any other &#x60;targeting&#x60; field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. RSA text updates use top-level &#x60;headlines&#x60;, &#x60;descriptions&#x60; and &#x60;finalUrls&#x60;. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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&#39;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 &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;. OpenAI Ads budget is lifetime-only (see &#x60;budget.type&#x60; below). **Google keyword replacement:** These edits affect the ad&#39;s entire ad group, including sibling ads. Positive (&#x60;targeting.keywords&#x60;) and negative (&#x60;targeting.negativeKeywords&#x60;) sets are independent: omit a field to leave that set unchanged, or send &#x60;[]&#x60; to remove every keyword of that kind. Zernio compares each supplied set with Google&#39;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 &#x60;matchType&#x60; means &#x60;broad&#x60;, not the existing criterion&#39;s match type. For example, resending an existing &#x60;{ \&quot;text\&quot;: \&quot;plumber\&quot;, \&quot;matchType\&quot;: \&quot;exact\&quot; }&#x60; preserves it; sending &#x60;\&quot;plumber\&quot;&#x60; 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&#39;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 &#x60;PATCH /v1/ads/keywords/{keywordId}&#x60; to pause/enable one keyword, or &#x60;DELETE /v1/ads/keywords/{keywordId}&#x60; to remove it.
562
+ # 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 &#x60;/v2/adgroup/update/&#x60;), and creative (via &#x60;/v2/ad/update/&#x60; patch-style: &#x60;headline&#x60; is ignored, &#x60;body&#x60; becomes &#x60;ad_text&#x60;). - **Google**: status, budget, KEYWORD edits via &#x60;targeting.keywords&#x60; / &#x60;targeting.negativeKeywords&#x60;, DEVICE bid adjustments via &#x60;targeting.devices&#x60;, LOCATION edits via &#x60;targeting.locations&#x60; (or the equivalent top-level &#x60;targeting.countries&#x60; / &#x60;regions&#x60; / &#x60;cities&#x60; / &#x60;zips&#x60; / &#x60;metros&#x60;), and LANGUAGE edits via &#x60;targeting.languages&#x60;. 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. Any other &#x60;targeting&#x60; field returns 400: Google cannot mutate it post-create without recreating the campaign. RSA text updates use top-level &#x60;headlines&#x60;, &#x60;descriptions&#x60; and &#x60;finalUrls&#x60;. Each supplied array replaces the full list; omit a field to preserve it. 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 for Google. - **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&#39;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 &#x60;targeting&#x60; or &#x60;creative&#x60; returns 501 with code &#x60;unsupported_platform_operation&#x60;. OpenAI Ads budget is lifetime-only (see &#x60;budget.type&#x60; 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&#39;s campaign. Send the complete list you want to keep. Zernio diffs it against the campaign&#39;s live criteria and sends the removes and the creates in ONE &#x60;googleAds:mutate&#x60;, 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 \&quot;remove my locations\&quot; means, so omit the field instead), and radius targeting (&#x60;customLocations&#x60;) returns 422 because it is a separate Google criterion type that this replacement neither creates nor removes. Send either &#x60;targeting.locations&#x60; or the top-level geo fields, not both: mixing them returns 400. **Google keyword replacement:** These edits affect the ad&#39;s entire ad group, including sibling ads. Positive (&#x60;targeting.keywords&#x60;) and negative (&#x60;targeting.negativeKeywords&#x60;) sets are independent: omit a field to leave that set unchanged, or send &#x60;[]&#x60; to remove every keyword of that kind. Zernio compares each supplied set with Google&#39;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 &#x60;matchType&#x60; means &#x60;broad&#x60;, not the existing criterion&#39;s match type. For example, resending an existing &#x60;{ \&quot;text\&quot;: \&quot;plumber\&quot;, \&quot;matchType\&quot;: \&quot;exact\&quot; }&#x60; preserves it; sending &#x60;\&quot;plumber\&quot;&#x60; 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&#39;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 &#x60;PATCH /v1/ads/keywords/{keywordId}&#x60; to pause/enable one keyword, or &#x60;DELETE /v1/ads/keywords/{keywordId}&#x60; to remove it.
563
563
  # @param ad_id
564
564
  # @param update_ad_request
565
565
  # @param [Hash] opts the optional parameters
@@ -689,7 +689,7 @@ describe 'AdCampaignsApi' do
689
689
 
690
690
  # unit tests for update_campaign_targeting
691
691
  # Edit a Google campaign&#39;s device, location, or language targeting
692
- # Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of &#x60;devices&#x60;, &#x60;locations&#x60;, &#x60;languages&#x60;; each provided field REPLACES that field&#39;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. &#x60;locations&#x60; accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with &#x60;countries&#x60;/&#x60;regions&#x60;/&#x60;cities&#x60;/&#x60;zips&#x60;/&#x60;metros&#x60; key lists (&#x60;key&#x60; from GET /v1/ads/targeting/search?dimension&#x3D;geo). Negative (excluded) locations are left untouched by this endpoint. &#x60;languages&#x60; is an array of Google&#39;s language codes (ISO 639-1, plus variants such as &#x60;zh_CN&#x60;); an unknown code returns 400. The response includes the refreshed &#x60;devices&#x60;/&#x60;locations&#x60;/&#x60;languages&#x60; state read back from Google after the edit, and invalidates the cached copy &#x60;GET&#x60; on this campaign would otherwise keep serving.
692
+ # Google Ads compliance row M.10: geo and language targeting set at creation must stay editable afterwards. Send at least one of &#x60;devices&#x60;, &#x60;locations&#x60;, &#x60;languages&#x60;; each provided field REPLACES that field&#39;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. &#x60;locations&#x60; accepts the same shapes as campaign creation: a bare array of ISO country codes, or an object with &#x60;countries&#x60;/&#x60;regions&#x60;/&#x60;cities&#x60;/&#x60;zips&#x60;/&#x60;metros&#x60; key lists (&#x60;key&#x60; from GET /v1/ads/targeting/search?dimension&#x3D;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 &#x60;locations&#x60; to leave targeting alone. The removes and the creates go out in ONE Google &#x60;googleAds:mutate&#x60;, so a failed edit leaves the campaign&#39;s previous set intact rather than a half-applied one. &#x60;languages&#x60; is an array of Google&#39;s language codes (ISO 639-1, plus variants such as &#x60;zh_CN&#x60;); an unknown code returns 400. The response includes the refreshed &#x60;devices&#x60;/&#x60;locations&#x60;/&#x60;languages&#x60; state read back from Google after the edit, and invalidates the cached copy &#x60;GET&#x60; on this campaign would otherwise keep serving.
693
693
  # @param campaign_id Google platform campaign ID
694
694
  # @param update_campaign_targeting_request
695
695
  # @param [Hash] opts the optional parameters
@@ -0,0 +1,32 @@
1
+ =begin
2
+ #Zernio API
3
+
4
+ #API reference for Zernio. Authenticate with a Bearer API key. Base URL: https://zernio.com/api Versioning and deprecation: all endpoints are versioned in the URL path (current version: /v1). Breaking changes only ship in a new path version; existing versions keep working. Deprecated operations are marked 'deprecated: true' in this spec and announced in the changelog (https://zernio.com/changelog) before removal. Errors: every 4xx/5xx response is application/json with a machine-readable 'code' and a human-readable 'error' message (see the ErrorResponse schema).
5
+
6
+ The version of the OpenAPI document: 1.0.4
7
+ Contact: support@zernio.com
8
+ Generated by: https://openapi-generator.tech
9
+ Generator version: 7.19.0
10
+
11
+ =end
12
+
13
+ require 'spec_helper'
14
+ require 'json'
15
+ require 'date'
16
+
17
+ # Unit tests for Zernio::UpdateAdRequestTargetingLocations
18
+ # Automatically generated by openapi-generator (https://openapi-generator.tech)
19
+ # Please update as you see appropriate
20
+ describe Zernio::UpdateAdRequestTargetingLocations do
21
+ describe '.openapi_one_of' do
22
+ it 'lists the items referenced in the oneOf array' do
23
+ expect(described_class.openapi_one_of).to_not be_empty
24
+ end
25
+ end
26
+
27
+ describe '.build' do
28
+ it 'returns the correct model' do
29
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
30
+ end
31
+ end
32
+ end
@@ -63,6 +63,18 @@ describe Zernio::UpdateAdRequestTargeting do
63
63
  end
64
64
  end
65
65
 
66
+ describe 'test attribute "locations"' do
67
+ it 'should work' do
68
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
69
+ end
70
+ end
71
+
72
+ describe 'test attribute "languages"' do
73
+ it 'should work' do
74
+ # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
75
+ end
76
+ end
77
+
66
78
  describe 'test attribute "interests"' do
67
79
  it 'should work' do
68
80
  # assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
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.926
4
+ version: 0.0.927
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenAPI-Generator
@@ -1776,6 +1776,7 @@ files:
1776
1776
  - docs/UpdateAdRequestTargetingInterestsInner.md
1777
1777
  - docs/UpdateAdRequestTargetingKeywordsInner.md
1778
1778
  - docs/UpdateAdRequestTargetingKeywordsInnerOneOf.md
1779
+ - docs/UpdateAdRequestTargetingLocations.md
1779
1780
  - docs/UpdateAdSet200Response.md
1780
1781
  - docs/UpdateAdSetRequest.md
1781
1782
  - docs/UpdateAdSetRequestBudget.md
@@ -3891,6 +3892,7 @@ files:
3891
3892
  - lib/zernio-sdk/models/update_ad_request_targeting_interests_inner.rb
3892
3893
  - lib/zernio-sdk/models/update_ad_request_targeting_keywords_inner.rb
3893
3894
  - lib/zernio-sdk/models/update_ad_request_targeting_keywords_inner_one_of.rb
3895
+ - lib/zernio-sdk/models/update_ad_request_targeting_locations.rb
3894
3896
  - lib/zernio-sdk/models/update_ad_set200_response.rb
3895
3897
  - lib/zernio-sdk/models/update_ad_set_request.rb
3896
3898
  - lib/zernio-sdk/models/update_ad_set_request_budget.rb
@@ -5985,6 +5987,7 @@ files:
5985
5987
  - spec/models/update_ad_request_targeting_interests_inner_spec.rb
5986
5988
  - spec/models/update_ad_request_targeting_keywords_inner_one_of_spec.rb
5987
5989
  - spec/models/update_ad_request_targeting_keywords_inner_spec.rb
5990
+ - spec/models/update_ad_request_targeting_locations_spec.rb
5988
5991
  - spec/models/update_ad_request_targeting_spec.rb
5989
5992
  - spec/models/update_ad_set200_response_spec.rb
5990
5993
  - spec/models/update_ad_set_request_budget_spec.rb
@@ -6358,7 +6361,7 @@ files:
6358
6361
  - spec/models/you_tube_video_retention_response_retention_curve_inner_spec.rb
6359
6362
  - spec/models/you_tube_video_retention_response_spec.rb
6360
6363
  - spec/spec_helper.rb
6361
- - zernio-sdk-0.0.926.gem
6364
+ - zernio-sdk-0.0.927.gem
6362
6365
  - zernio-sdk.gemspec
6363
6366
  homepage: https://openapi-generator.tech
6364
6367
  licenses:
@@ -7683,6 +7686,7 @@ test_files:
7683
7686
  - spec/models/get_gmb_attribute_metadata200_response_spec.rb
7684
7687
  - spec/models/list_inbox_conversations200_response_meta_accounts_skipped_inner_spec.rb
7685
7688
  - spec/models/request_sms_sender_id_limit_increase_request_spec.rb
7689
+ - spec/models/update_ad_request_targeting_locations_spec.rb
7686
7690
  - spec/models/get_call200_response_spec.rb
7687
7691
  - spec/models/list_conversion_actions200_response_spec.rb
7688
7692
  - spec/models/send_inbox_message_request_interactive_action_one_of7_sections_inner_product_items_inner_spec.rb
Binary file