late-sdk 0.0.856 → 0.0.857
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 +19 -2
- data/docs/AdCampaignsApi.md +364 -6
- data/docs/{ListAdKeywords200ResponseKeywordsInner.md → AdKeyword.md} +7 -3
- data/docs/AdKeywordMetrics.md +30 -0
- data/docs/AddAdKeywords201Response.md +18 -0
- data/docs/AddAdKeywordsRequest.md +24 -0
- data/docs/AddAdKeywordsRequestKeywordsInner.md +20 -0
- data/docs/AddAdKeywordsRequestKeywordsInnerAnyOf.md +20 -0
- data/docs/CreateStandaloneAdRequest.md +4 -2
- data/docs/KeywordEntry.md +49 -0
- data/docs/ListAdKeywords200Response.md +1 -1
- data/docs/ListCampaignNegativeKeywords200Response.md +18 -0
- data/docs/ListCampaignNegativeKeywords200ResponseKeywordsInner.md +22 -0
- data/docs/RemoveAdKeyword200Response.md +20 -0
- data/docs/ReplaceCampaignNegativeKeywords200Response.md +22 -0
- data/docs/ReplaceCampaignNegativeKeywordsRequest.md +20 -0
- data/docs/UpdateAdKeyword200Response.md +18 -0
- data/docs/{UpdateAdStatusRequest.md → UpdateAdKeywordRequest.md} +2 -2
- data/lib/zernio-sdk/api/ad_campaigns_api.rb +358 -9
- data/lib/zernio-sdk/models/{list_ad_keywords200_response_keywords_inner.rb → ad_keyword.rb} +28 -8
- data/lib/zernio-sdk/models/ad_keyword_metrics.rb +207 -0
- data/lib/zernio-sdk/models/add_ad_keywords201_response.rb +149 -0
- data/lib/zernio-sdk/models/add_ad_keywords_request.rb +250 -0
- data/lib/zernio-sdk/models/add_ad_keywords_request_keywords_inner.rb +103 -0
- data/lib/zernio-sdk/models/add_ad_keywords_request_keywords_inner_any_of.rb +225 -0
- data/lib/zernio-sdk/models/create_standalone_ad_request.rb +55 -5
- data/lib/zernio-sdk/models/keyword_entry.rb +105 -0
- data/lib/zernio-sdk/models/list_ad_keywords200_response.rb +1 -1
- data/lib/zernio-sdk/models/list_campaign_negative_keywords200_response.rb +149 -0
- data/lib/zernio-sdk/models/list_campaign_negative_keywords200_response_keywords_inner.rb +199 -0
- data/lib/zernio-sdk/models/remove_ad_keyword200_response.rb +157 -0
- data/lib/zernio-sdk/models/replace_campaign_negative_keywords200_response.rb +170 -0
- data/lib/zernio-sdk/models/replace_campaign_negative_keywords_request.rb +219 -0
- data/lib/zernio-sdk/models/update_ad_keyword200_response.rb +147 -0
- data/lib/zernio-sdk/models/{update_ad_status_request.rb → update_ad_keyword_request.rb} +3 -3
- data/lib/zernio-sdk/version.rb +1 -1
- data/lib/zernio-sdk.rb +14 -2
- data/openapi.yaml +257 -21
- data/spec/api/ad_campaigns_api_spec.rb +64 -1
- data/spec/models/ad_keyword_metrics_spec.rb +72 -0
- data/spec/models/{list_ad_keywords200_response_keywords_inner_spec.rb → ad_keyword_spec.rb} +18 -6
- data/spec/models/add_ad_keywords201_response_spec.rb +36 -0
- data/spec/models/add_ad_keywords_request_keywords_inner_any_of_spec.rb +46 -0
- data/spec/models/add_ad_keywords_request_keywords_inner_spec.rb +21 -0
- data/spec/models/add_ad_keywords_request_spec.rb +54 -0
- data/spec/models/create_standalone_ad_request_spec.rb +6 -0
- data/spec/models/keyword_entry_spec.rb +32 -0
- data/spec/models/list_campaign_negative_keywords200_response_keywords_inner_spec.rb +52 -0
- data/spec/models/list_campaign_negative_keywords200_response_spec.rb +36 -0
- data/spec/models/remove_ad_keyword200_response_spec.rb +42 -0
- data/spec/models/replace_campaign_negative_keywords200_response_spec.rb +48 -0
- data/spec/models/replace_campaign_negative_keywords_request_spec.rb +46 -0
- data/spec/models/update_ad_keyword200_response_spec.rb +36 -0
- data/spec/models/{update_ad_status_request_spec.rb → update_ad_keyword_request_spec.rb} +6 -6
- data/zernio-sdk-0.0.857.gem +0 -0
- metadata +58 -10
- data/zernio-sdk-0.0.856.gem +0 -0
data/openapi.yaml
CHANGED
|
@@ -9182,6 +9182,49 @@ components:
|
|
|
9182
9182
|
page_id: { type: string }
|
|
9183
9183
|
earliestAd: { type: string, format: date-time }
|
|
9184
9184
|
latestAd: { type: string, format: date-time }
|
|
9185
|
+
AdKeyword:
|
|
9186
|
+
type: object
|
|
9187
|
+
properties:
|
|
9188
|
+
id: { type: string }
|
|
9189
|
+
accountId: { type: string, description: Social account ID owning the sync }
|
|
9190
|
+
profileId: { type: string }
|
|
9191
|
+
platform: { type: string, enum: [google] }
|
|
9192
|
+
adAccountId: { type: string, description: Google customer ID }
|
|
9193
|
+
campaignId: { type: string }
|
|
9194
|
+
campaignName: { type: [string, "null"] }
|
|
9195
|
+
campaignStatus: { type: [string, "null"] }
|
|
9196
|
+
adSetId: { type: string, description: Google ad group ID }
|
|
9197
|
+
adSetName: { type: [string, "null"] }
|
|
9198
|
+
adSetStatus: { type: [string, "null"] }
|
|
9199
|
+
keyword: { type: string }
|
|
9200
|
+
matchType: { type: string, enum: [exact, phrase, broad, unknown] }
|
|
9201
|
+
status: { type: string, enum: [active, paused] }
|
|
9202
|
+
negative: { type: boolean }
|
|
9203
|
+
qualityScore: { type: [integer, "null"], description: 'Google Quality Score, 1-10. Null when unrated.' }
|
|
9204
|
+
syncedAt: { type: [string, "null"], format: date-time }
|
|
9205
|
+
metrics:
|
|
9206
|
+
type: [object, "null"]
|
|
9207
|
+
description: 'Trailing 30-day window. Null on rows synced before the metrics columns existed (re-synced on the keyword''s next weekly sweep).'
|
|
9208
|
+
properties:
|
|
9209
|
+
windowDays: { type: integer }
|
|
9210
|
+
clicks: { type: integer }
|
|
9211
|
+
impressions: { type: integer }
|
|
9212
|
+
cost: { type: number, description: 'Account currency, not USD-normalized' }
|
|
9213
|
+
conversions: { type: number }
|
|
9214
|
+
firstPageCpc: { type: [number, "null"], description: Account currency }
|
|
9215
|
+
firstPositionCpc: { type: [number, "null"], description: Account currency }
|
|
9216
|
+
KeywordEntry:
|
|
9217
|
+
description: 'A Google Search keyword: a bare string (BROAD match), or an object naming the match type.'
|
|
9218
|
+
oneOf:
|
|
9219
|
+
- type: string
|
|
9220
|
+
minLength: 1
|
|
9221
|
+
maxLength: 80
|
|
9222
|
+
description: 'Keyword text; defaults to BROAD match'
|
|
9223
|
+
- type: object
|
|
9224
|
+
required: [text]
|
|
9225
|
+
properties:
|
|
9226
|
+
text: { type: string, minLength: 1, maxLength: 80 }
|
|
9227
|
+
matchType: { type: string, enum: [exact, phrase, broad] }
|
|
9185
9228
|
ConversionEvent:
|
|
9186
9229
|
type: object
|
|
9187
9230
|
description: |
|
|
@@ -41308,30 +41351,126 @@ paths:
|
|
|
41308
41351
|
properties:
|
|
41309
41352
|
keywords:
|
|
41310
41353
|
type: array
|
|
41311
|
-
items:
|
|
41312
|
-
type: object
|
|
41313
|
-
properties:
|
|
41314
|
-
id: { type: string }
|
|
41315
|
-
accountId: { type: string, description: Social account ID owning the sync }
|
|
41316
|
-
profileId: { type: string }
|
|
41317
|
-
platform: { type: string, enum: [google] }
|
|
41318
|
-
adAccountId: { type: string, description: Google customer ID }
|
|
41319
|
-
campaignId: { type: string }
|
|
41320
|
-
campaignName: { type: [string, "null"] }
|
|
41321
|
-
campaignStatus: { type: [string, "null"] }
|
|
41322
|
-
adSetId: { type: string, description: Google ad group ID }
|
|
41323
|
-
adSetName: { type: [string, "null"] }
|
|
41324
|
-
adSetStatus: { type: [string, "null"] }
|
|
41325
|
-
keyword: { type: string }
|
|
41326
|
-
matchType: { type: string, enum: [exact, phrase, broad, unknown] }
|
|
41327
|
-
status: { type: string, enum: [active, paused] }
|
|
41328
|
-
negative: { type: boolean }
|
|
41329
|
-
syncedAt: { type: [string, "null"], format: date-time }
|
|
41354
|
+
items: { $ref: '#/components/schemas/AdKeyword' }
|
|
41330
41355
|
pagination: { $ref: '#/components/schemas/Pagination' }
|
|
41331
41356
|
'400': { $ref: '#/components/responses/BadRequest' }
|
|
41332
41357
|
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41333
41358
|
'403':
|
|
41334
41359
|
description: Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
|
|
41360
|
+
post:
|
|
41361
|
+
x-resource-group: "ads"
|
|
41362
|
+
operationId: addAdKeywords
|
|
41363
|
+
tags: ["Ad Campaigns"]
|
|
41364
|
+
x-platforms: ["google"]
|
|
41365
|
+
summary: Add Search keywords to an ad group
|
|
41366
|
+
description: |
|
|
41367
|
+
Adds one or more keyword criteria to an existing Google Search ad group,
|
|
41368
|
+
without touching the keywords already there (unlike the whole-set diff on
|
|
41369
|
+
`PUT /v1/ads/{adId}`, `keywords`/`negativeKeywords` in `platformSpecificData`,
|
|
41370
|
+
which replaces the set). Set `negative: true` to add ad-group-level negatives
|
|
41371
|
+
instead of positive keywords.
|
|
41372
|
+
security:
|
|
41373
|
+
- bearerAuth: []
|
|
41374
|
+
requestBody:
|
|
41375
|
+
required: true
|
|
41376
|
+
content:
|
|
41377
|
+
application/json:
|
|
41378
|
+
schema:
|
|
41379
|
+
type: object
|
|
41380
|
+
required: [accountId, adSetId, keywords]
|
|
41381
|
+
properties:
|
|
41382
|
+
accountId: { type: string, description: Social account ID (Google Ads) }
|
|
41383
|
+
adSetId: { type: string, description: Google ad group ID to add the keywords to }
|
|
41384
|
+
keywords:
|
|
41385
|
+
type: array
|
|
41386
|
+
minItems: 1
|
|
41387
|
+
maxItems: 1000
|
|
41388
|
+
items:
|
|
41389
|
+
anyOf:
|
|
41390
|
+
- type: string
|
|
41391
|
+
description: 'Keyword text; defaults to BROAD match'
|
|
41392
|
+
- type: object
|
|
41393
|
+
required: [text]
|
|
41394
|
+
properties:
|
|
41395
|
+
text: { type: string, minLength: 1, maxLength: 80 }
|
|
41396
|
+
matchType: { type: string, enum: [exact, phrase, broad] }
|
|
41397
|
+
negative: { type: boolean, default: false, description: 'Add as ad-group-level negatives instead of positive keywords' }
|
|
41398
|
+
responses:
|
|
41399
|
+
'201':
|
|
41400
|
+
description: Keywords added
|
|
41401
|
+
content:
|
|
41402
|
+
application/json:
|
|
41403
|
+
schema:
|
|
41404
|
+
type: object
|
|
41405
|
+
properties:
|
|
41406
|
+
keywords:
|
|
41407
|
+
type: array
|
|
41408
|
+
items: { $ref: '#/components/schemas/AdKeyword' }
|
|
41409
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
41410
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41411
|
+
'404': { description: 'The ad group ("adSetId") was not found for this account.' }
|
|
41412
|
+
'501': { description: Only available on Google Ads accounts }
|
|
41413
|
+
|
|
41414
|
+
/v1/ads/keywords/{keywordId}:
|
|
41415
|
+
patch:
|
|
41416
|
+
x-resource-group: "ads"
|
|
41417
|
+
operationId: updateAdKeyword
|
|
41418
|
+
tags: ["Ad Campaigns"]
|
|
41419
|
+
x-platforms: ["google"]
|
|
41420
|
+
summary: Pause or enable a Search keyword
|
|
41421
|
+
description: |
|
|
41422
|
+
Changes `ad_group_criterion.status` for one keyword criterion (M.140).
|
|
41423
|
+
Negative keywords have no status on Google and cannot be paused or enabled.
|
|
41424
|
+
security:
|
|
41425
|
+
- bearerAuth: []
|
|
41426
|
+
parameters:
|
|
41427
|
+
- { name: keywordId, in: path, required: true, schema: { type: string }, description: Zernio keyword ID (not the Google criterion ID) }
|
|
41428
|
+
requestBody:
|
|
41429
|
+
required: true
|
|
41430
|
+
content:
|
|
41431
|
+
application/json:
|
|
41432
|
+
schema:
|
|
41433
|
+
type: object
|
|
41434
|
+
required: [status]
|
|
41435
|
+
properties:
|
|
41436
|
+
status: { type: string, enum: [active, paused] }
|
|
41437
|
+
responses:
|
|
41438
|
+
'200':
|
|
41439
|
+
description: Keyword updated
|
|
41440
|
+
content:
|
|
41441
|
+
application/json:
|
|
41442
|
+
schema:
|
|
41443
|
+
type: object
|
|
41444
|
+
properties:
|
|
41445
|
+
keyword: { $ref: '#/components/schemas/AdKeyword' }
|
|
41446
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
41447
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41448
|
+
'404': { description: Keyword not found }
|
|
41449
|
+
'422': { description: 'Negative keywords have no status on Google; they cannot be paused or enabled.' }
|
|
41450
|
+
delete:
|
|
41451
|
+
x-resource-group: "ads"
|
|
41452
|
+
operationId: removeAdKeyword
|
|
41453
|
+
tags: ["Ad Campaigns"]
|
|
41454
|
+
x-platforms: ["google"]
|
|
41455
|
+
summary: Remove a Search keyword
|
|
41456
|
+
description: Removes one keyword criterion (positive or negative) from its ad group (M.140).
|
|
41457
|
+
security:
|
|
41458
|
+
- bearerAuth: []
|
|
41459
|
+
parameters:
|
|
41460
|
+
- { name: keywordId, in: path, required: true, schema: { type: string }, description: Zernio keyword ID (not the Google criterion ID) }
|
|
41461
|
+
responses:
|
|
41462
|
+
'200':
|
|
41463
|
+
description: Keyword removed
|
|
41464
|
+
content:
|
|
41465
|
+
application/json:
|
|
41466
|
+
schema:
|
|
41467
|
+
type: object
|
|
41468
|
+
properties:
|
|
41469
|
+
removed: { type: boolean, description: Always true on success }
|
|
41470
|
+
keywordId: { type: string }
|
|
41471
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
41472
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41473
|
+
'404': { description: Keyword not found }
|
|
41335
41474
|
|
|
41336
41475
|
/v1/ads/campaigns:
|
|
41337
41476
|
get:
|
|
@@ -41653,6 +41792,102 @@ paths:
|
|
|
41653
41792
|
'404': { description: Campaign not found }
|
|
41654
41793
|
'501': { description: Operation not supported on this platform }
|
|
41655
41794
|
|
|
41795
|
+
/v1/ads/campaigns/{campaignId}/negative-keywords:
|
|
41796
|
+
get:
|
|
41797
|
+
x-resource-group: "ads"
|
|
41798
|
+
operationId: listCampaignNegativeKeywords
|
|
41799
|
+
tags: ["Ad Campaigns"]
|
|
41800
|
+
x-platforms: ["google"]
|
|
41801
|
+
summary: List campaign-level negative keywords
|
|
41802
|
+
description: |
|
|
41803
|
+
Returns the campaign-level negative keywords (`campaign_criterion.negative`),
|
|
41804
|
+
distinct from the ad-group-level negatives under `GET /v1/ads/keywords`. Read
|
|
41805
|
+
live from Google on every call (not synced to Postgres), and gated by the
|
|
41806
|
+
shared Google Ads operations budget like every other on-demand Google surface.
|
|
41807
|
+
|
|
41808
|
+
The platform is always discovered from the campaign itself; a non-Google
|
|
41809
|
+
campaign returns 501 rather than 404, whether or not `platform` was passed.
|
|
41810
|
+
security:
|
|
41811
|
+
- bearerAuth: []
|
|
41812
|
+
parameters:
|
|
41813
|
+
- { name: campaignId, in: path, required: true, schema: { type: string }, description: Platform campaign ID }
|
|
41814
|
+
- { name: platform, in: query, schema: { type: string, enum: [facebook, instagram, tiktok, linkedin, pinterest, google, twitter, openai] }, description: 'Optional and NOT authoritative: the resolved campaign''s own platform decides 200 vs 501, never this hint.' }
|
|
41815
|
+
responses:
|
|
41816
|
+
'200':
|
|
41817
|
+
description: Campaign-level negative keywords
|
|
41818
|
+
content:
|
|
41819
|
+
application/json:
|
|
41820
|
+
schema:
|
|
41821
|
+
type: object
|
|
41822
|
+
properties:
|
|
41823
|
+
keywords:
|
|
41824
|
+
type: array
|
|
41825
|
+
items:
|
|
41826
|
+
type: object
|
|
41827
|
+
properties:
|
|
41828
|
+
criterionId: { type: string }
|
|
41829
|
+
text: { type: string }
|
|
41830
|
+
matchType: { type: string, enum: [exact, phrase, broad] }
|
|
41831
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41832
|
+
'404': { description: Campaign not found }
|
|
41833
|
+
'429': { description: Google Ads operations budget exhausted; retry later }
|
|
41834
|
+
'501': { description: Only available on Google Ads campaigns }
|
|
41835
|
+
put:
|
|
41836
|
+
x-resource-group: "ads"
|
|
41837
|
+
operationId: replaceCampaignNegativeKeywords
|
|
41838
|
+
tags: ["Ad Campaigns"]
|
|
41839
|
+
x-platforms: ["google"]
|
|
41840
|
+
summary: Replace campaign-level negative keywords
|
|
41841
|
+
description: |
|
|
41842
|
+
Replaces the FULL set of campaign-level negative keywords (C.270): the desired
|
|
41843
|
+
list is diffed against what Google already has, and the difference is applied
|
|
41844
|
+
as one `create`/`remove` mutate. Send an empty array to clear every campaign
|
|
41845
|
+
negative.
|
|
41846
|
+
|
|
41847
|
+
The platform is always discovered from the campaign itself; a non-Google
|
|
41848
|
+
campaign returns 501 rather than 404, whether or not `platform` was sent.
|
|
41849
|
+
security:
|
|
41850
|
+
- bearerAuth: []
|
|
41851
|
+
parameters:
|
|
41852
|
+
- { name: campaignId, in: path, required: true, schema: { type: string }, description: Platform campaign ID }
|
|
41853
|
+
requestBody:
|
|
41854
|
+
required: true
|
|
41855
|
+
content:
|
|
41856
|
+
application/json:
|
|
41857
|
+
schema:
|
|
41858
|
+
type: object
|
|
41859
|
+
required: [keywords]
|
|
41860
|
+
properties:
|
|
41861
|
+
platform: { type: string, enum: [facebook, instagram, tiktok, linkedin, pinterest, google, twitter, openai], description: 'Optional and NOT authoritative: the resolved campaign''s own platform decides 200 vs 501, never this hint.' }
|
|
41862
|
+
keywords:
|
|
41863
|
+
type: array
|
|
41864
|
+
maxItems: 1000
|
|
41865
|
+
items: { $ref: '#/components/schemas/KeywordEntry' }
|
|
41866
|
+
responses:
|
|
41867
|
+
'200':
|
|
41868
|
+
description: Campaign-level negative keywords replaced
|
|
41869
|
+
content:
|
|
41870
|
+
application/json:
|
|
41871
|
+
schema:
|
|
41872
|
+
type: object
|
|
41873
|
+
properties:
|
|
41874
|
+
created: { type: integer, description: Negative criteria newly created on Google }
|
|
41875
|
+
removed: { type: integer, description: Negative criteria removed from Google }
|
|
41876
|
+
keywords:
|
|
41877
|
+
type: array
|
|
41878
|
+
description: The full negative-keyword set after the replace
|
|
41879
|
+
items:
|
|
41880
|
+
type: object
|
|
41881
|
+
properties:
|
|
41882
|
+
criterionId: { type: string }
|
|
41883
|
+
text: { type: string }
|
|
41884
|
+
matchType: { type: string, enum: [exact, phrase, broad] }
|
|
41885
|
+
'400': { $ref: '#/components/responses/BadRequest' }
|
|
41886
|
+
'401': { $ref: '#/components/responses/Unauthorized' }
|
|
41887
|
+
'404': { description: Campaign not found }
|
|
41888
|
+
'429': { description: Google Ads operations budget exhausted; retry later }
|
|
41889
|
+
'501': { description: Only available on Google Ads campaigns }
|
|
41890
|
+
|
|
41656
41891
|
/v1/ads/campaigns/bulk-status:
|
|
41657
41892
|
post:
|
|
41658
41893
|
x-resource-group: "ads"
|
|
@@ -45586,8 +45821,9 @@ paths:
|
|
|
45586
45821
|
items: { type: string, enum: [mobile, desktop] }
|
|
45587
45822
|
audienceId: { type: string, description: Custom audience ID for targeting }
|
|
45588
45823
|
campaignType: { type: string, enum: [display, search], default: display, description: Google only }
|
|
45589
|
-
keywords: { type: array, maxItems: 1000, items: {
|
|
45590
|
-
negativeKeywords: { type: array,
|
|
45824
|
+
keywords: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/KeywordEntry' }, description: "Google Search only. Keywords on the new ad group; entries are strings (BROAD) or { text, matchType }. Editable later via PUT /v1/ads/{adId} targeting.keywords." }
|
|
45825
|
+
negativeKeywords: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/KeywordEntry' }, description: "Google Search only; other platforms return 400. Ad-group-level negative keywords on the new ad group. Editable later via PUT /v1/ads/{adId} targeting.negativeKeywords." }
|
|
45826
|
+
campaignNegativeKeywords: { type: array, maxItems: 1000, items: { $ref: '#/components/schemas/KeywordEntry' }, description: "Google Search only; other platforms return 400. Campaign-level negative keywords (campaign_criterion.negative), created alongside the ad group. Editable later via PUT /v1/ads/campaigns/{campaignId}/negative-keywords." }
|
|
45591
45827
|
additionalHeadlines: { type: array, items: { type: string }, description: "Google Search RSA only. Extra headlines." }
|
|
45592
45828
|
additionalDescriptions: { type: array, items: { type: string }, description: "Google Search RSA only. Extra descriptions." }
|
|
45593
45829
|
sitelinks:
|
|
@@ -32,6 +32,18 @@ describe 'AdCampaignsApi' do
|
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
# unit tests for add_ad_keywords
|
|
36
|
+
# Add Search keywords to an ad group
|
|
37
|
+
# Adds one or more keyword criteria to an existing Google Search ad group, without touching the keywords already there (unlike the whole-set diff on `PUT /v1/ads/{adId}`, `keywords`/`negativeKeywords` in `platformSpecificData`, which replaces the set). Set `negative: true` to add ad-group-level negatives instead of positive keywords.
|
|
38
|
+
# @param add_ad_keywords_request
|
|
39
|
+
# @param [Hash] opts the optional parameters
|
|
40
|
+
# @return [AddAdKeywords201Response]
|
|
41
|
+
describe 'add_ad_keywords test' do
|
|
42
|
+
it 'should work' do
|
|
43
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
35
47
|
# unit tests for attach_campaign_assets
|
|
36
48
|
# Attach extension assets to a Google Search campaign
|
|
37
49
|
# Attach sitelinks, callouts and/or structured snippets to an already-existing Google Search campaign — the same builders POST /v1/ads/create uses, but without rebuilding the hierarchy. At least one of sitelinks, callouts or structuredSnippets is required. Google-only. Other platforms have no equivalent extension surface and return 501. Approval status is Google-async; poll `asset.policy_summary` after review. Assets stay in the account library even if the campaign is later deleted.
|
|
@@ -319,6 +331,44 @@ describe 'AdCampaignsApi' do
|
|
|
319
331
|
end
|
|
320
332
|
end
|
|
321
333
|
|
|
334
|
+
# unit tests for list_campaign_negative_keywords
|
|
335
|
+
# List campaign-level negative keywords
|
|
336
|
+
# Returns the campaign-level negative keywords (`campaign_criterion.negative`), distinct from the ad-group-level negatives under `GET /v1/ads/keywords`. Read live from Google on every call (not synced to Postgres), and gated by the shared Google Ads operations budget like every other on-demand Google surface. The platform is always discovered from the campaign itself; a non-Google campaign returns 501 rather than 404, whether or not `platform` was passed.
|
|
337
|
+
# @param campaign_id Platform campaign ID
|
|
338
|
+
# @param [Hash] opts the optional parameters
|
|
339
|
+
# @option opts [String] :platform Optional and NOT authoritative: the resolved campaign's own platform decides 200 vs 501, never this hint.
|
|
340
|
+
# @return [ListCampaignNegativeKeywords200Response]
|
|
341
|
+
describe 'list_campaign_negative_keywords test' do
|
|
342
|
+
it 'should work' do
|
|
343
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# unit tests for remove_ad_keyword
|
|
348
|
+
# Remove a Search keyword
|
|
349
|
+
# Removes one keyword criterion (positive or negative) from its ad group (M.140).
|
|
350
|
+
# @param keyword_id Zernio keyword ID (not the Google criterion ID)
|
|
351
|
+
# @param [Hash] opts the optional parameters
|
|
352
|
+
# @return [RemoveAdKeyword200Response]
|
|
353
|
+
describe 'remove_ad_keyword test' do
|
|
354
|
+
it 'should work' do
|
|
355
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# unit tests for replace_campaign_negative_keywords
|
|
360
|
+
# Replace campaign-level negative keywords
|
|
361
|
+
# Replaces the FULL set of campaign-level negative keywords (C.270): the desired list is diffed against what Google already has, and the difference is applied as one `create`/`remove` mutate. Send an empty array to clear every campaign negative. The platform is always discovered from the campaign itself; a non-Google campaign returns 501 rather than 404, whether or not `platform` was sent.
|
|
362
|
+
# @param campaign_id Platform campaign ID
|
|
363
|
+
# @param replace_campaign_negative_keywords_request
|
|
364
|
+
# @param [Hash] opts the optional parameters
|
|
365
|
+
# @return [ReplaceCampaignNegativeKeywords200Response]
|
|
366
|
+
describe 'replace_campaign_negative_keywords test' do
|
|
367
|
+
it 'should work' do
|
|
368
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
322
372
|
# unit tests for update_ad
|
|
323
373
|
# Update ad
|
|
324
374
|
# 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, and KEYWORD edits via `targeting.keywords` / `targeting.negativeKeywords` — each list you send becomes the FULL new set of its kind on the ad group (criteria not in the list are removed); a kind left out is untouched. Any other `targeting` field returns 400: Google cannot mutate broad targeting post-create without recreating the campaign. `creative` returns 501. - **LinkedIn**: status, budget, targeting (geo countries only, applied to the LinkedIn Campaign via PARTIAL_UPDATE), 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).
|
|
@@ -358,6 +408,19 @@ describe 'AdCampaignsApi' do
|
|
|
358
408
|
end
|
|
359
409
|
end
|
|
360
410
|
|
|
411
|
+
# unit tests for update_ad_keyword
|
|
412
|
+
# Pause or enable a Search keyword
|
|
413
|
+
# Changes `ad_group_criterion.status` for one keyword criterion (M.140). Negative keywords have no status on Google and cannot be paused or enabled.
|
|
414
|
+
# @param keyword_id Zernio keyword ID (not the Google criterion ID)
|
|
415
|
+
# @param update_ad_keyword_request
|
|
416
|
+
# @param [Hash] opts the optional parameters
|
|
417
|
+
# @return [UpdateAdKeyword200Response]
|
|
418
|
+
describe 'update_ad_keyword test' do
|
|
419
|
+
it 'should work' do
|
|
420
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
361
424
|
# unit tests for update_ad_set
|
|
362
425
|
# Update an ad set
|
|
363
426
|
# Ad-set-level writes. Use this for ABO budget updates, ad-set-scoped pause/resume, bid-strategy edits, Meta value-rule-set attach/detach, and Meta-only post-launch delivery settings via `platformSpecificData`. At least one updatable field is required. Value rule sets (Meta only, see `/v1/ads/value-rule-sets`): - ATTACH or REPLACE: send `valueRuleSetId`. Attachment is driven by the id's presence, so `valueRulesApplied: true` is optional. Sending a different id replaces the previous association; there is no separate replace call. - DETACH: send `valueRulesApplied: false` and OMIT `valueRuleSetId`. - Sending `valueRulesApplied: false` TOGETHER with `valueRuleSetId` returns 400 `mutually_exclusive_fields`. This is deliberate: Meta attaches the rule set whenever `value_rule_set_id` is present, even with `value_rules_applied` false, so echoing stored state while asking to detach would silently keep the bid adjustments live. - Eligibility: only ad sets on `LOWEST_COST_WITHOUT_CAP` or `COST_CAP`. Meta rejects the rest server-side. - Read back with `GET /v1/ads/ad-sets/{adSetId}?fields=value_rule_set_id`. Meta does not document `value_rules_applied` as a readable ad-set field, so the boolean cannot be read back. Bid strategy compatibility (per Meta's spec): - `LOWEST_COST_WITHOUT_CAP`: no `bidAmount`, no `roasAverageFloor`. - `LOWEST_COST_WITH_BID_CAP` / `COST_CAP`: `bidAmount` REQUIRED (whole currency units). - `LOWEST_COST_WITH_MIN_ROAS`: `roasAverageFloor` REQUIRED (decimal multiplier, e.g. 2.0 = 2.0x ROAS). - Meta only: send `bidAmount` WITHOUT `bidStrategy` to change the cap amount on an ad set under a COST_CAP / LOWEST_COST_WITH_BID_CAP parent campaign, leaving the strategy itself (inherited from the campaign) untouched. `roasAverageFloor` without `bidStrategy` is rejected (it has no meaning outside LOWEST_COST_WITH_MIN_ROAS). Delivery settings are validated by Meta against the campaign objective; incompatible combinations (e.g. a billingEvent the optimization goal doesn't allow) surface as 400s from Meta. When updating `budget` on an ABO campaign: if the parent campaign is CBO, the response is 409 with code BUDGET_LEVEL_MISMATCH — route to PUT /v1/ads/campaigns/{campaignId} instead.
|
|
@@ -388,7 +451,7 @@ describe 'AdCampaignsApi' do
|
|
|
388
451
|
# Pause or resume a single ad
|
|
389
452
|
# Ad-scoped pause/resume — touches ONLY this ad, never its parent ad set or campaign (so sibling ads keep running). Thin wrapper over the `status` field of PUT /v1/ads/{adId}, for callers that want a URL symmetric to /v1/ads/campaigns/{campaignId}/status and /v1/ads/ad-sets/{adSetId}/status. `{adId}` accepts the same identifier dialects as GET/PUT /v1/ads/{adId} (Zernio hex `_id`, Meta numeric `platformAdId`, or the creative's effective story/media IDs). `platform` is inferred from the ad, so it's not required in the body. Ads in terminal statuses (rejected, completed, cancelled) and no-op flips (already in the target state) are skipped.
|
|
390
453
|
# @param ad_id Zernio `_id` (hex), Meta `platformAdId` (numeric), or one of the creative's effective story/media IDs.
|
|
391
|
-
# @param
|
|
454
|
+
# @param update_ad_keyword_request
|
|
392
455
|
# @param [Hash] opts the optional parameters
|
|
393
456
|
# @return [UpdateAdStatus200Response]
|
|
394
457
|
describe 'update_ad_status test' do
|
|
@@ -0,0 +1,72 @@
|
|
|
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::AdKeywordMetrics
|
|
18
|
+
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
+
# Please update as you see appropriate
|
|
20
|
+
describe Zernio::AdKeywordMetrics do
|
|
21
|
+
#let(:instance) { Zernio::AdKeywordMetrics.new }
|
|
22
|
+
|
|
23
|
+
describe 'test an instance of AdKeywordMetrics' do
|
|
24
|
+
it 'should create an instance of AdKeywordMetrics' do
|
|
25
|
+
# uncomment below to test the instance creation
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::AdKeywordMetrics)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'test attribute "window_days"' do
|
|
31
|
+
it 'should work' do
|
|
32
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'test attribute "clicks"' do
|
|
37
|
+
it 'should work' do
|
|
38
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'test attribute "impressions"' do
|
|
43
|
+
it 'should work' do
|
|
44
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe 'test attribute "cost"' do
|
|
49
|
+
it 'should work' do
|
|
50
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
describe 'test attribute "conversions"' do
|
|
55
|
+
it 'should work' do
|
|
56
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe 'test attribute "first_page_cpc"' do
|
|
61
|
+
it 'should work' do
|
|
62
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe 'test attribute "first_position_cpc"' 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
|
+
end
|
|
@@ -14,16 +14,16 @@ require 'spec_helper'
|
|
|
14
14
|
require 'json'
|
|
15
15
|
require 'date'
|
|
16
16
|
|
|
17
|
-
# Unit tests for Zernio::
|
|
17
|
+
# Unit tests for Zernio::AdKeyword
|
|
18
18
|
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
19
|
# Please update as you see appropriate
|
|
20
|
-
describe Zernio::
|
|
21
|
-
#let(:instance) { Zernio::
|
|
20
|
+
describe Zernio::AdKeyword do
|
|
21
|
+
#let(:instance) { Zernio::AdKeyword.new }
|
|
22
22
|
|
|
23
|
-
describe 'test an instance of
|
|
24
|
-
it 'should create an instance of
|
|
23
|
+
describe 'test an instance of AdKeyword' do
|
|
24
|
+
it 'should create an instance of AdKeyword' do
|
|
25
25
|
# uncomment below to test the instance creation
|
|
26
|
-
#expect(instance).to be_instance_of(Zernio::
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::AdKeyword)
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -129,10 +129,22 @@ describe Zernio::ListAdKeywords200ResponseKeywordsInner do
|
|
|
129
129
|
end
|
|
130
130
|
end
|
|
131
131
|
|
|
132
|
+
describe 'test attribute "quality_score"' do
|
|
133
|
+
it 'should work' do
|
|
134
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
132
138
|
describe 'test attribute "synced_at"' do
|
|
133
139
|
it 'should work' do
|
|
134
140
|
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
135
141
|
end
|
|
136
142
|
end
|
|
137
143
|
|
|
144
|
+
describe 'test attribute "metrics"' do
|
|
145
|
+
it 'should work' do
|
|
146
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
138
150
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
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::AddAdKeywords201Response
|
|
18
|
+
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
+
# Please update as you see appropriate
|
|
20
|
+
describe Zernio::AddAdKeywords201Response do
|
|
21
|
+
#let(:instance) { Zernio::AddAdKeywords201Response.new }
|
|
22
|
+
|
|
23
|
+
describe 'test an instance of AddAdKeywords201Response' do
|
|
24
|
+
it 'should create an instance of AddAdKeywords201Response' do
|
|
25
|
+
# uncomment below to test the instance creation
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::AddAdKeywords201Response)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'test attribute "keywords"' do
|
|
31
|
+
it 'should work' do
|
|
32
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
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::AddAdKeywordsRequestKeywordsInnerAnyOf
|
|
18
|
+
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
+
# Please update as you see appropriate
|
|
20
|
+
describe Zernio::AddAdKeywordsRequestKeywordsInnerAnyOf do
|
|
21
|
+
#let(:instance) { Zernio::AddAdKeywordsRequestKeywordsInnerAnyOf.new }
|
|
22
|
+
|
|
23
|
+
describe 'test an instance of AddAdKeywordsRequestKeywordsInnerAnyOf' do
|
|
24
|
+
it 'should create an instance of AddAdKeywordsRequestKeywordsInnerAnyOf' do
|
|
25
|
+
# uncomment below to test the instance creation
|
|
26
|
+
#expect(instance).to be_instance_of(Zernio::AddAdKeywordsRequestKeywordsInnerAnyOf)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe 'test attribute "text"' do
|
|
31
|
+
it 'should work' do
|
|
32
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'test attribute "match_type"' do
|
|
37
|
+
it 'should work' do
|
|
38
|
+
# assertion here. ref: https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/
|
|
39
|
+
# validator = Petstore::EnumTest::EnumAttributeValidator.new('String', ["exact", "phrase", "broad"])
|
|
40
|
+
# validator.allowable_values.each do |value|
|
|
41
|
+
# expect { instance.match_type = value }.not_to raise_error
|
|
42
|
+
# end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
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::AddAdKeywordsRequestKeywordsInner
|
|
18
|
+
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
19
|
+
# Please update as you see appropriate
|
|
20
|
+
describe Zernio::AddAdKeywordsRequestKeywordsInner do
|
|
21
|
+
end
|