late-sdk 0.0.925 → 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 +4 -4
- data/README.md +1 -0
- data/docs/AdCampaignsApi.md +2 -2
- data/docs/AdTargetingApi.md +3 -3
- data/docs/SearchAdTargeting200ResponseResultsInner.md +1 -1
- data/docs/TargetingSpec.md +4 -4
- data/docs/UpdateAdRequestTargeting.md +5 -1
- data/docs/UpdateAdRequestTargetingLocations.md +49 -0
- data/lib/zernio-sdk/api/ad_campaigns_api.rb +4 -4
- data/lib/zernio-sdk/api/ad_targeting_api.rb +5 -5
- data/lib/zernio-sdk/models/search_ad_targeting200_response_results_inner.rb +1 -1
- data/lib/zernio-sdk/models/targeting_spec.rb +4 -4
- data/lib/zernio-sdk/models/update_ad_request_targeting.rb +23 -1
- data/lib/zernio-sdk/models/update_ad_request_targeting_locations.rb +105 -0
- data/lib/zernio-sdk/version.rb +1 -1
- data/lib/zernio-sdk.rb +1 -0
- data/openapi.yaml +65 -11
- data/spec/api/ad_campaigns_api_spec.rb +2 -2
- data/spec/api/ad_targeting_api_spec.rb +2 -2
- data/spec/models/update_ad_request_targeting_locations_spec.rb +32 -0
- data/spec/models/update_ad_request_targeting_spec.rb +12 -0
- data/zernio-sdk-0.0.927.gem +0 -0
- metadata +6 -2
- data/zernio-sdk-0.0.925.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: 3b522983a22f33b813eb3ed655ce02f772c4888899221e73b07b24a556691ba4
|
|
4
|
+
data.tar.gz: f9720e017147152e181119b0e9c29498ed99e1e476da7bc6bef6f6250b37434f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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)
|
data/docs/AdCampaignsApi.md
CHANGED
|
@@ -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`,
|
|
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
|
|
data/docs/AdTargetingApi.md
CHANGED
|
@@ -295,7 +295,7 @@ end
|
|
|
295
295
|
|
|
296
296
|
Search targeting options
|
|
297
297
|
|
|
298
|
-
Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
298
|
+
Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` - `industry`, `jobFunction`, `seniority`, `companySize`: the LinkedIn-only B2B facets, whose URNs feed `TargetingSpec.industries`/`jobFunctions`/`seniorities`/`companySizes` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. LinkedIn B2B searches (`industry`, `jobFunction`, `seniority`, `companySize`) return the full URN to pass straight back, so no URN id fragment has to be assembled by hand: `urn:li:industry:4`, `urn:li:function:8`, `urn:li:seniority:6`, `urn:li:staffCountRange:(51,200)`. Only `industry` is a server-side name search (LinkedIn's typeahead finder). LinkedIn exposes no typeahead for job functions, seniorities and company sizes, so Zernio fetches each whole table (26, 10 and 9 entries), caches it, and does the matching, ranking and `limit` cutoff itself. Those three never carry `audienceSize`, and `countryCode` and `geoType` are not applied to any of the four. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
299
299
|
|
|
300
300
|
### Examples
|
|
301
301
|
|
|
@@ -312,7 +312,7 @@ api_instance = Zernio::AdTargetingApi.new
|
|
|
312
312
|
account_id = 'account_id_example' # String | Account ID (a connected account on the target ad platform).
|
|
313
313
|
q = 'q_example' # String | Search query. For geo, the locality name only (no region/country suffix).
|
|
314
314
|
opts = {
|
|
315
|
-
dimension: 'geo', # String | What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias.
|
|
315
|
+
dimension: 'geo', # String | What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics, `industry`/`jobFunction`/`seniority`/`companySize` resolve LinkedIn B2B facets (LinkedIn only). Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias.
|
|
316
316
|
geo_type: 'all', # String | Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`.
|
|
317
317
|
country_code: 'country_code_example', # String | ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search.
|
|
318
318
|
limit: 56 # Integer | Maximum results to return.
|
|
@@ -351,7 +351,7 @@ end
|
|
|
351
351
|
| ---- | ---- | ----------- | ----- |
|
|
352
352
|
| **account_id** | **String** | Account ID (a connected account on the target ad platform). | |
|
|
353
353
|
| **q** | **String** | Search query. For geo, the locality name only (no region/country suffix). | |
|
|
354
|
-
| **dimension** | **String** | What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias. | [optional][default to 'interest'] |
|
|
354
|
+
| **dimension** | **String** | What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics, `industry`/`jobFunction`/`seniority`/`companySize` resolve LinkedIn B2B facets (LinkedIn only). Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias. | [optional][default to 'interest'] |
|
|
355
355
|
| **geo_type** | **String** | Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`. | [optional][default to 'city'] |
|
|
356
356
|
| **country_code** | **String** | ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search. | [optional] |
|
|
357
357
|
| **limit** | **Integer** | Maximum results to return. | [optional][default to 25] |
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
| ---- | ---- | ----------- | ----- |
|
|
7
7
|
| **id** | **String** | The platform's opaque id. Use as a geo `key` (regions/cities/zips/metros) or an entity `id` (interests/behaviors) in TargetingSpec. | |
|
|
8
8
|
| **name** | **String** | Human-readable label. | |
|
|
9
|
-
| **type** | **String** | What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income). | |
|
|
9
|
+
| **type** | **String** | What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income, industry, jobFunction, seniority, companySize). | |
|
|
10
10
|
| **path** | **Array<String>** | Optional breadcrumb of parent labels (e.g. ['United States', 'California', 'Los Angeles']). Disambiguates same-named results. | [optional] |
|
|
11
11
|
| **audience_size** | **Integer** | Optional estimated reachable users for this option, when the platform returns it. | [optional] |
|
|
12
12
|
|
data/docs/TargetingSpec.md
CHANGED
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
| **work_positions** | [**Array<CreateStandaloneAdRequestBehaviorsInner>**](CreateStandaloneAdRequestBehaviorsInner.md) | Meta only. Job title entities from /v1/ads/targeting/search?dimension=workPosition. Not interchangeable with the LinkedIn `jobTitles` URN fragments. | [optional] |
|
|
24
24
|
| **work_employers** | [**Array<CreateStandaloneAdRequestBehaviorsInner>**](CreateStandaloneAdRequestBehaviorsInner.md) | Meta only. Employer entities from /v1/ads/targeting/search?dimension=workEmployer. | [optional] |
|
|
25
25
|
| **work_industries** | [**Array<CreateStandaloneAdRequestBehaviorsInner>**](CreateStandaloneAdRequestBehaviorsInner.md) | Meta only. Work-industry entities from /v1/ads/targeting/search?dimension=workIndustry. Not interchangeable with the LinkedIn `industries` URN fragments. | [optional] |
|
|
26
|
-
| **industries** | **Array<String>** | LinkedIn B2B only. Industry URN id fragments. | [optional] |
|
|
27
|
-
| **company_sizes** | **Array<String>** | LinkedIn B2B only. | [optional] |
|
|
28
|
-
| **seniorities** | **Array<String>** | LinkedIn B2B only. | [optional] |
|
|
29
|
-
| **job_functions** | **Array<String>** | LinkedIn B2B only. | [optional] |
|
|
26
|
+
| **industries** | **Array<String>** | LinkedIn B2B only. Industry URN id fragments, or the full urn:li:industry:* URN from /v1/ads/targeting/search?dimension=industry. | [optional] |
|
|
27
|
+
| **company_sizes** | **Array<String>** | LinkedIn B2B only. Single-letter size codes (A to I), or the full urn:li:staffCountRange:* URN from /v1/ads/targeting/search?dimension=companySize. | [optional] |
|
|
28
|
+
| **seniorities** | **Array<String>** | LinkedIn B2B only. Seniority URN id fragments, or the full urn:li:seniority:* URN from /v1/ads/targeting/search?dimension=seniority. | [optional] |
|
|
29
|
+
| **job_functions** | **Array<String>** | LinkedIn B2B only. Function URN id fragments, or the full urn:li:function:* URN from /v1/ads/targeting/search?dimension=jobFunction. | [optional] |
|
|
30
30
|
| **audience_include** | **Array<String>** | Platform audience IDs to include, as returned by GET /v1/ads/audiences (Meta custom audience ids, TikTok audience ids, Pinterest customer list ids, LinkedIn segment ids (the platformAudienceId from GET /v1/ads/audiences; Zernio resolves it to the targetable LinkedIn ad segment, an unknown id returns 400), Google user list ids, X custom audience ids). Not supported on OpenAI (400). | [optional] |
|
|
31
31
|
| **audience_exclude** | **Array<String>** | Platform audience IDs to exclude; same ID formats as audienceInclude. Not supported on OpenAI (400). | [optional] |
|
|
32
32
|
|
|
@@ -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>** |
|
|
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`,
|
|
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 `/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`,
|
|
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 `/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.
|
|
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'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 `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.
|
|
3671
|
+
# 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.
|
|
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
|
|
@@ -295,11 +295,11 @@ module Zernio
|
|
|
295
295
|
end
|
|
296
296
|
|
|
297
297
|
# Search targeting options
|
|
298
|
-
# Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
298
|
+
# Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` - `industry`, `jobFunction`, `seniority`, `companySize`: the LinkedIn-only B2B facets, whose URNs feed `TargetingSpec.industries`/`jobFunctions`/`seniorities`/`companySizes` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. LinkedIn B2B searches (`industry`, `jobFunction`, `seniority`, `companySize`) return the full URN to pass straight back, so no URN id fragment has to be assembled by hand: `urn:li:industry:4`, `urn:li:function:8`, `urn:li:seniority:6`, `urn:li:staffCountRange:(51,200)`. Only `industry` is a server-side name search (LinkedIn's typeahead finder). LinkedIn exposes no typeahead for job functions, seniorities and company sizes, so Zernio fetches each whole table (26, 10 and 9 entries), caches it, and does the matching, ranking and `limit` cutoff itself. Those three never carry `audienceSize`, and `countryCode` and `geoType` are not applied to any of the four. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
299
299
|
# @param account_id [String] Account ID (a connected account on the target ad platform).
|
|
300
300
|
# @param q [String] Search query. For geo, the locality name only (no region/country suffix).
|
|
301
301
|
# @param [Hash] opts the optional parameters
|
|
302
|
-
# @option opts [String] :dimension What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias. (default to 'interest')
|
|
302
|
+
# @option opts [String] :dimension What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics, `industry`/`jobFunction`/`seniority`/`companySize` resolve LinkedIn B2B facets (LinkedIn only). Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias. (default to 'interest')
|
|
303
303
|
# @option opts [String] :geo_type Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`. (default to 'city')
|
|
304
304
|
# @option opts [String] :country_code ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search.
|
|
305
305
|
# @option opts [Integer] :limit Maximum results to return. (default to 25)
|
|
@@ -310,11 +310,11 @@ module Zernio
|
|
|
310
310
|
end
|
|
311
311
|
|
|
312
312
|
# Search targeting options
|
|
313
|
-
# Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
313
|
+
# Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` - `industry`, `jobFunction`, `seniority`, `companySize`: the LinkedIn-only B2B facets, whose URNs feed `TargetingSpec.industries`/`jobFunctions`/`seniorities`/`companySizes` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. LinkedIn B2B searches (`industry`, `jobFunction`, `seniority`, `companySize`) return the full URN to pass straight back, so no URN id fragment has to be assembled by hand: `urn:li:industry:4`, `urn:li:function:8`, `urn:li:seniority:6`, `urn:li:staffCountRange:(51,200)`. Only `industry` is a server-side name search (LinkedIn's typeahead finder). LinkedIn exposes no typeahead for job functions, seniorities and company sizes, so Zernio fetches each whole table (26, 10 and 9 entries), caches it, and does the matching, ranking and `limit` cutoff itself. Those three never carry `audienceSize`, and `countryCode` and `geoType` are not applied to any of the four. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
314
314
|
# @param account_id [String] Account ID (a connected account on the target ad platform).
|
|
315
315
|
# @param q [String] Search query. For geo, the locality name only (no region/country suffix).
|
|
316
316
|
# @param [Hash] opts the optional parameters
|
|
317
|
-
# @option opts [String] :dimension What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias. (default to 'interest')
|
|
317
|
+
# @option opts [String] :dimension What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics, `industry`/`jobFunction`/`seniority`/`companySize` resolve LinkedIn B2B facets (LinkedIn only). Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias. (default to 'interest')
|
|
318
318
|
# @option opts [String] :geo_type Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`. (default to 'city')
|
|
319
319
|
# @option opts [String] :country_code ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search.
|
|
320
320
|
# @option opts [Integer] :limit Maximum results to return. (default to 25)
|
|
@@ -331,7 +331,7 @@ module Zernio
|
|
|
331
331
|
if @api_client.config.client_side_validation && q.nil?
|
|
332
332
|
fail ArgumentError, "Missing the required parameter 'q' when calling AdTargetingApi.search_ad_targeting"
|
|
333
333
|
end
|
|
334
|
-
allowable_values = ["geo", "interest", "behavior", "income", "language", "workPosition", "workEmployer", "workIndustry"]
|
|
334
|
+
allowable_values = ["geo", "interest", "behavior", "income", "language", "workPosition", "workEmployer", "workIndustry", "industry", "jobFunction", "seniority", "companySize"]
|
|
335
335
|
if @api_client.config.client_side_validation && opts[:'dimension'] && !allowable_values.include?(opts[:'dimension'])
|
|
336
336
|
fail ArgumentError, "invalid value for \"dimension\", must be one of #{allowable_values}"
|
|
337
337
|
end
|
|
@@ -21,7 +21,7 @@ module Zernio
|
|
|
21
21
|
# Human-readable label.
|
|
22
22
|
attr_accessor :name
|
|
23
23
|
|
|
24
|
-
# What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income).
|
|
24
|
+
# What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income, industry, jobFunction, seniority, companySize).
|
|
25
25
|
attr_accessor :type
|
|
26
26
|
|
|
27
27
|
# Optional breadcrumb of parent labels (e.g. ['United States', 'California', 'Los Angeles']). Disambiguates same-named results.
|
|
@@ -72,16 +72,16 @@ module Zernio
|
|
|
72
72
|
# Meta only. Work-industry entities from /v1/ads/targeting/search?dimension=workIndustry. Not interchangeable with the LinkedIn `industries` URN fragments.
|
|
73
73
|
attr_accessor :work_industries
|
|
74
74
|
|
|
75
|
-
# LinkedIn B2B only. Industry URN id fragments.
|
|
75
|
+
# LinkedIn B2B only. Industry URN id fragments, or the full urn:li:industry:* URN from /v1/ads/targeting/search?dimension=industry.
|
|
76
76
|
attr_accessor :industries
|
|
77
77
|
|
|
78
|
-
# LinkedIn B2B only.
|
|
78
|
+
# LinkedIn B2B only. Single-letter size codes (A to I), or the full urn:li:staffCountRange:* URN from /v1/ads/targeting/search?dimension=companySize.
|
|
79
79
|
attr_accessor :company_sizes
|
|
80
80
|
|
|
81
|
-
# LinkedIn B2B only.
|
|
81
|
+
# LinkedIn B2B only. Seniority URN id fragments, or the full urn:li:seniority:* URN from /v1/ads/targeting/search?dimension=seniority.
|
|
82
82
|
attr_accessor :seniorities
|
|
83
83
|
|
|
84
|
-
# LinkedIn B2B only.
|
|
84
|
+
# LinkedIn B2B only. Function URN id fragments, or the full urn:li:function:* URN from /v1/ads/targeting/search?dimension=jobFunction.
|
|
85
85
|
attr_accessor :job_functions
|
|
86
86
|
|
|
87
87
|
# Platform audience IDs to include, as returned by GET /v1/ads/audiences (Meta custom audience ids, TikTok audience ids, Pinterest customer list ids, LinkedIn segment ids (the platformAudienceId from GET /v1/ads/audiences; Zernio resolves it to the targetable LinkedIn ad segment, an unknown id returns 400), Google user list ids, X custom audience ids). Not supported on OpenAI (400).
|
|
@@ -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
|
data/lib/zernio-sdk/version.rb
CHANGED
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
|
@@ -9238,10 +9238,10 @@ components:
|
|
|
9238
9238
|
properties:
|
|
9239
9239
|
id: { type: string }
|
|
9240
9240
|
name: { type: string }
|
|
9241
|
-
industries: { type: array, items: { type: string }, description: "LinkedIn B2B only. Industry URN id fragments." }
|
|
9242
|
-
companySizes: { type: array, items: { type: string }, description: "LinkedIn B2B only." }
|
|
9243
|
-
seniorities: { type: array, items: { type: string }, description: "LinkedIn B2B only." }
|
|
9244
|
-
jobFunctions: { type: array, items: { type: string }, description: "LinkedIn B2B only." }
|
|
9241
|
+
industries: { type: array, items: { type: string }, description: "LinkedIn B2B only. Industry URN id fragments, or the full urn:li:industry:* URN from /v1/ads/targeting/search?dimension=industry." }
|
|
9242
|
+
companySizes: { type: array, items: { type: string }, description: "LinkedIn B2B only. Single-letter size codes (A to I), or the full urn:li:staffCountRange:* URN from /v1/ads/targeting/search?dimension=companySize." }
|
|
9243
|
+
seniorities: { type: array, items: { type: string }, description: "LinkedIn B2B only. Seniority URN id fragments, or the full urn:li:seniority:* URN from /v1/ads/targeting/search?dimension=seniority." }
|
|
9244
|
+
jobFunctions: { type: array, items: { type: string }, description: "LinkedIn B2B only. Function URN id fragments, or the full urn:li:function:* URN from /v1/ads/targeting/search?dimension=jobFunction." }
|
|
9245
9245
|
audienceInclude: { type: array, items: { type: string }, description: 'Platform audience IDs to include, as returned by GET /v1/ads/audiences (Meta custom audience ids, TikTok audience ids, Pinterest customer list ids, LinkedIn segment ids (the platformAudienceId from GET /v1/ads/audiences; Zernio resolves it to the targetable LinkedIn ad segment, an unknown id returns 400), Google user list ids, X custom audience ids). Not supported on OpenAI (400).' }
|
|
9246
9246
|
audienceExclude: { type: array, items: { type: string }, description: 'Platform audience IDs to exclude; same ID formats as audienceInclude. Not supported on OpenAI (400).' }
|
|
9247
9247
|
MetaCreativeFeatures:
|
|
@@ -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`,
|
|
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
|
|
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,
|
|
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:
|
|
@@ -52814,6 +52857,8 @@ paths:
|
|
|
52814
52857
|
- `language`: Google-only
|
|
52815
52858
|
- `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose
|
|
52816
52859
|
ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries`
|
|
52860
|
+
- `industry`, `jobFunction`, `seniority`, `companySize`: the LinkedIn-only B2B facets, whose
|
|
52861
|
+
URNs feed `TargetingSpec.industries`/`jobFunctions`/`seniorities`/`companySizes`
|
|
52817
52862
|
|
|
52818
52863
|
Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only).
|
|
52819
52864
|
Work industries are a fixed ~30-entry Meta catalog with no server-side query,
|
|
@@ -52838,6 +52883,15 @@ paths:
|
|
|
52838
52883
|
`urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`,
|
|
52839
52884
|
`POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`.
|
|
52840
52885
|
|
|
52886
|
+
LinkedIn B2B searches (`industry`, `jobFunction`, `seniority`, `companySize`) return the
|
|
52887
|
+
full URN to pass straight back, so no URN id fragment has to be assembled by hand:
|
|
52888
|
+
`urn:li:industry:4`, `urn:li:function:8`, `urn:li:seniority:6`,
|
|
52889
|
+
`urn:li:staffCountRange:(51,200)`. Only `industry` is a server-side name search
|
|
52890
|
+
(LinkedIn's typeahead finder). LinkedIn exposes no typeahead for job functions,
|
|
52891
|
+
seniorities and company sizes, so Zernio fetches each whole table (26, 10 and 9 entries),
|
|
52892
|
+
caches it, and does the matching, ranking and `limit` cutoff itself. Those three never
|
|
52893
|
+
carry `audienceSize`, and `countryCode` and `geoType` are not applied to any of the four.
|
|
52894
|
+
|
|
52841
52895
|
Google geo searches resolve against Google's geoTargetConstants and return
|
|
52842
52896
|
every matching level in one list; `geoType` is not applied (Google's
|
|
52843
52897
|
`target_type` is an open taxonomy that does not map one-to-one onto the
|
|
@@ -52875,7 +52929,7 @@ paths:
|
|
|
52875
52929
|
parameters:
|
|
52876
52930
|
- { name: accountId, in: query, required: true, schema: { type: string }, description: "Account ID (a connected account on the target ad platform)." }
|
|
52877
52931
|
- { name: q, in: query, required: true, schema: { type: string }, description: "Search query. For geo, the locality name only (no region/country suffix)." }
|
|
52878
|
-
- { name: dimension, in: query, required: false, schema: { type: string, enum: [geo, interest, behavior, income, language, workPosition, workEmployer, workIndustry], default: interest }, description: "What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias." }
|
|
52932
|
+
- { name: dimension, in: query, required: false, schema: { type: string, enum: [geo, interest, behavior, income, language, workPosition, workEmployer, workIndustry, industry, jobFunction, seniority, companySize], default: interest }, description: "What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics, `industry`/`jobFunction`/`seniority`/`companySize` resolve LinkedIn B2B facets (LinkedIn only). Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias." }
|
|
52879
52933
|
- { name: geoType, in: query, required: false, schema: { type: string, enum: [all, country, region, city, subcity, neighborhood, place, zip, metro_area, geo_market], default: city }, description: "Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`." }
|
|
52880
52934
|
- { name: countryCode, in: query, required: false, schema: { type: string, minLength: 2, maxLength: 2 }, description: "ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search." }
|
|
52881
52935
|
- { name: limit, in: query, required: false, schema: { type: integer, minimum: 1, maximum: 100, default: 25 }, description: "Maximum results to return." }
|
|
@@ -52896,7 +52950,7 @@ paths:
|
|
|
52896
52950
|
properties:
|
|
52897
52951
|
id: { type: string, description: "The platform's opaque id. Use as a geo `key` (regions/cities/zips/metros) or an entity `id` (interests/behaviors) in TargetingSpec." }
|
|
52898
52952
|
name: { type: string, description: "Human-readable label." }
|
|
52899
|
-
type: { type: string, description: "What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income)." }
|
|
52953
|
+
type: { type: string, description: "What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income, industry, jobFunction, seniority, companySize)." }
|
|
52900
52954
|
path: { type: array, items: { type: string }, description: "Optional breadcrumb of parent labels (e.g. ['United States', 'California', 'Los Angeles']). Disambiguates same-named results." }
|
|
52901
52955
|
audienceSize: { type: [integer, "null"], description: "Optional estimated reachable users for this option, when the platform returns it." }
|
|
52902
52956
|
'400':
|
|
@@ -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 `/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`,
|
|
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 `/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.
|
|
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'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 `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.
|
|
692
|
+
# 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.
|
|
693
693
|
# @param campaign_id Google platform campaign ID
|
|
694
694
|
# @param update_campaign_targeting_request
|
|
695
695
|
# @param [Hash] opts the optional parameters
|
|
@@ -83,11 +83,11 @@ describe 'AdTargetingApi' do
|
|
|
83
83
|
|
|
84
84
|
# unit tests for search_ad_targeting
|
|
85
85
|
# Search targeting options
|
|
86
|
-
# Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
86
|
+
# Resolve a human-readable query into the platform's opaque targeting ids used in the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and `interests`/`behaviors` entity ids) on `POST /v1/ads/create`, `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences. The `dimension` param selects what is searched: - `geo`: locations, further scoped by `geoType` - `interest` - `behavior` - `income` - `language`: Google-only - `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries` - `industry`, `jobFunction`, `seniority`, `companySize`: the LinkedIn-only B2B facets, whose URNs feed `TargetingSpec.industries`/`jobFunctions`/`seniorities`/`companySizes` Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only). Work industries are a fixed ~30-entry Meta catalog with no server-side query, so `workIndustry` matching, ranking and `limit` happen in Zernio. `language` is likewise a fixed, checked-in table of Google's targetable `language_constant` rows (id, ISO code, name) matched by name or code, capped at 20, with no network call; its ids feed `TargetingSpec.languages`. Results are normalized across platforms into a single shape, so the same client code consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results. TikTok geo searches return every matching level in one list (`type` is `country`, `region`, `city`, `district`, or `metro` for DMA areas), and `geoType` is not applied. Results are scoped to the advertiser's targetable markets, and every id is usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`. LinkedIn geo searches also return every matching level in one list, and neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only returns a name and a URN per result, with no level or country field to filter on. Every result has `type` set to `location`, and its id is a `urn:li:geo:*` URN usable as a `regions[].key` on `POST /v1/ads/create`, `POST /v1/ads/boost` and `POST /v1/ads/targeting/reach-estimate`. LinkedIn B2B searches (`industry`, `jobFunction`, `seniority`, `companySize`) return the full URN to pass straight back, so no URN id fragment has to be assembled by hand: `urn:li:industry:4`, `urn:li:function:8`, `urn:li:seniority:6`, `urn:li:staffCountRange:(51,200)`. Only `industry` is a server-side name search (LinkedIn's typeahead finder). LinkedIn exposes no typeahead for job functions, seniorities and company sizes, so Zernio fetches each whole table (26, 10 and 9 entries), caches it, and does the matching, ranking and `limit` cutoff itself. Those three never carry `audienceSize`, and `countryCode` and `geoType` are not applied to any of the four. Google geo searches resolve against Google's geoTargetConstants and return every matching level in one list; `geoType` is not applied (Google's `target_type` is an open taxonomy that does not map one-to-one onto the `geoType` enum), so filter client-side on the returned `type` (`country`, `region`, `city`, `zip`, `metro`, or the lowercased Google target type for rarer levels). `countryCode` scopes the search to one country. Each id is Google's numeric criterion id, usable as a `regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google city radius is not supported (pass a `customLocations` lat/lng pin for a radius); country targeting also accepts plain ISO codes via `countries` with no search call. Pinterest resolves against three whole-catalog endpoints (interests, locations, regions) with no server-side query or pagination, so matching, ranking and the `limit` cutoff all happen in Zernio; the catalog is independent of any ad account and results never carry `audienceSize`. Names come back localized to the connected Pinterest account's language (there is no way to force a locale), so match against whatever language that account returns. `geoType` routes to a different Pinterest catalog: - `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`) - `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on `POST /v1/ads/create`) - `all` and the default `city` merge both catalogs with honest per-entry `type`s, since Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal city search - `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest exposes no postal-code catalog, pass postal codes directly as `targeting.zips: [{ key }]` on `POST /v1/ads/create` For geo queries, `q` should contain only the locality name (e.g. `\"Amsterdam\"`, not `\"Amsterdam, NL\"`). Use `countryCode` to disambiguate.
|
|
87
87
|
# @param account_id Account ID (a connected account on the target ad platform).
|
|
88
88
|
# @param q Search query. For geo, the locality name only (no region/country suffix).
|
|
89
89
|
# @param [Hash] opts the optional parameters
|
|
90
|
-
# @option opts [String] :dimension What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics. Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias.
|
|
90
|
+
# @option opts [String] :dimension What to search. `geo` resolves locations (scope further with `geoType`), `interest`/`behavior` resolve audience entities, `income` resolves income-tier options, `language` resolves Google's targetable language_constant table (Google only), `workPosition`/`workEmployer`/`workIndustry` resolve Meta work demographics, `industry`/`jobFunction`/`seniority`/`companySize` resolve LinkedIn B2B facets (LinkedIn only). Defaults to `interest` for backward compatibility with the deprecated /v1/ads/interests alias.
|
|
91
91
|
# @option opts [String] :geo_type Only used when `dimension=geo`. The kind of location to resolve. `all` searches every type in one relevance-ranked call. Defaults to `city`.
|
|
92
92
|
# @option opts [String] :country_code ISO 3166-1 alpha-2 country code (e.g. NL) to scope a geo search.
|
|
93
93
|
# @option opts [Integer] :limit Maximum results to return.
|
|
@@ -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.
|
|
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.
|
|
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
|
data/zernio-sdk-0.0.925.gem
DELETED
|
Binary file
|