diff --git a/packages/nodes-base/nodes/Google/Ads/CampaignDescription.ts b/packages/nodes-base/nodes/Google/Ads/CampaignDescription.ts index ca30e47a3a..413ad611cb 100644 --- a/packages/nodes-base/nodes/Google/Ads/CampaignDescription.ts +++ b/packages/nodes-base/nodes/Google/Ads/CampaignDescription.ts @@ -11,7 +11,7 @@ async function processCampaignSearchResponse( _inputData: INodeExecutionData[], responseData: IN8nHttpFullResponse, ): Promise { - const results = (responseData.body as IDataObject).results as GoogleAdsCampaignElement; + const results = ((responseData.body as IDataObject).results as GoogleAdsCampaignElement) ?? []; return results.map((result) => ({ json: { @@ -41,7 +41,7 @@ export const campaignOperations: INodeProperties[] = [ routing: { request: { method: 'POST', - url: '={{"/v17/customers/" + $parameter["clientCustomerId"].toString().replace(/-/g, "") + "/googleAds:search"}}', + url: '={{"/v20/customers/" + $parameter["clientCustomerId"].toString().replace(/-/g, "") + "/googleAds:search"}}', body: { query: '={{ "' + @@ -89,7 +89,7 @@ export const campaignOperations: INodeProperties[] = [ routing: { request: { method: 'POST', - url: '={{"/v17/customers/" + $parameter["clientCustomerId"].toString().replace(/-/g, "") + "/googleAds:search"}}', + url: '={{"/v20/customers/" + $parameter["clientCustomerId"].toString().replace(/-/g, "") + "/googleAds:search"}}', returnFullResponse: true, body: { query: diff --git a/packages/nodes-base/nodes/Google/Ads/GoogleAds.node.ts b/packages/nodes-base/nodes/Google/Ads/GoogleAds.node.ts index 458408e311..e085cc3968 100644 --- a/packages/nodes-base/nodes/Google/Ads/GoogleAds.node.ts +++ b/packages/nodes-base/nodes/Google/Ads/GoogleAds.node.ts @@ -24,7 +24,7 @@ export class GoogleAds implements INodeType { testedBy: { request: { method: 'GET', - url: '/v17/customers:listAccessibleCustomers', + url: '/v20/customers:listAccessibleCustomers', }, }, }, diff --git a/packages/nodes-base/nodes/Google/Ads/__test__/node/GoogleAds.node.test.ts b/packages/nodes-base/nodes/Google/Ads/__test__/node/GoogleAds.node.test.ts new file mode 100644 index 0000000000..10c9d1e87c --- /dev/null +++ b/packages/nodes-base/nodes/Google/Ads/__test__/node/GoogleAds.node.test.ts @@ -0,0 +1,161 @@ +import { NodeTestHarness } from '@nodes-testing/node-test-harness'; +import nock from 'nock'; + +import getResult from './fixtures/get.json'; +import getManyResult from './fixtures/getMany.json'; + +describe('Google Ads Node', () => { + const credentials = { + googleAdsOAuth2Api: { + oauthTokenData: { + access_token: 'access-token', + }, + developerToken: 'test-developer-token', + }, + }; + + describe('get', () => { + const googleAdsNock = nock('https://googleads.googleapis.com'); + + beforeAll(() => { + googleAdsNock + .post('/v20/customers/4445556666/googleAds:search', { + query: + 'select ' + + 'campaign.id, ' + + 'campaign.name, ' + + 'campaign_budget.amount_micros, ' + + 'campaign_budget.period,' + + 'campaign.status,' + + 'campaign.optimization_score,' + + 'campaign.advertising_channel_type,' + + 'campaign.advertising_channel_sub_type,' + + 'metrics.impressions,' + + 'metrics.interactions,' + + 'metrics.interaction_rate,' + + 'metrics.average_cost,' + + 'metrics.cost_micros,' + + 'metrics.conversions,' + + 'metrics.cost_per_conversion,' + + 'metrics.conversions_from_interactions_rate,' + + 'metrics.video_views,' + + 'metrics.average_cpm,' + + 'metrics.ctr ' + + 'from campaign ' + + 'where campaign.id = 12345678901', + }) + .matchHeader('login-customer-id', '1112223333') + .reply(200, getResult); + }); + + afterAll(() => googleAdsNock.done()); + + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['get.workflow.json'], + }); + }); + + describe('getMany', () => { + const googleAdsNock = nock('https://googleads.googleapis.com'); + + beforeAll(() => { + googleAdsNock + .post('/v20/customers/4445556666/googleAds:search', { + query: + 'select ' + + 'campaign.id, ' + + 'campaign.name, ' + + 'campaign_budget.amount_micros, ' + + 'campaign_budget.period,' + + 'campaign.status,' + + 'campaign.optimization_score,' + + 'campaign.advertising_channel_type,' + + 'campaign.advertising_channel_sub_type,' + + 'metrics.impressions,' + + 'metrics.interactions,' + + 'metrics.interaction_rate,' + + 'metrics.average_cost,' + + 'metrics.cost_micros,' + + 'metrics.conversions,' + + 'metrics.cost_per_conversion,' + + 'metrics.conversions_from_interactions_rate,' + + 'metrics.video_views,' + + 'metrics.average_cpm,' + + 'metrics.ctr ' + + 'from campaign ' + + 'where campaign.id > 0 ', + }) + .matchHeader('login-customer-id', '1112223333') + .reply(200, getManyResult); + + googleAdsNock + .post('/v20/customers/4445556666/googleAds:search', { + query: + 'select ' + + 'campaign.id, ' + + 'campaign.name, ' + + 'campaign_budget.amount_micros, ' + + 'campaign_budget.period,' + + 'campaign.status,' + + 'campaign.optimization_score,' + + 'campaign.advertising_channel_type,' + + 'campaign.advertising_channel_sub_type,' + + 'metrics.impressions,' + + 'metrics.interactions,' + + 'metrics.interaction_rate,' + + 'metrics.average_cost,' + + 'metrics.cost_micros,' + + 'metrics.conversions,' + + 'metrics.cost_per_conversion,' + + 'metrics.conversions_from_interactions_rate,' + + 'metrics.video_views,' + + 'metrics.average_cpm,' + + 'metrics.ctr ' + + 'from campaign ' + + 'where campaign.id > 0 ' + + ' and segments.date DURING LAST_7_DAYS ' + + " and campaign.status = 'ENABLED'", + }) + .matchHeader('login-customer-id', '1112223333') + .reply(200, getManyResult); + + googleAdsNock + .post('/v20/customers/4445556666/googleAds:search', { + query: + 'select ' + + 'campaign.id, ' + + 'campaign.name, ' + + 'campaign_budget.amount_micros, ' + + 'campaign_budget.period,' + + 'campaign.status,' + + 'campaign.optimization_score,' + + 'campaign.advertising_channel_type,' + + 'campaign.advertising_channel_sub_type,' + + 'metrics.impressions,' + + 'metrics.interactions,' + + 'metrics.interaction_rate,' + + 'metrics.average_cost,' + + 'metrics.cost_micros,' + + 'metrics.conversions,' + + 'metrics.cost_per_conversion,' + + 'metrics.conversions_from_interactions_rate,' + + 'metrics.video_views,' + + 'metrics.average_cpm,' + + 'metrics.ctr ' + + 'from campaign ' + + 'where campaign.id > 0 ' + + " and campaign.status = 'REMOVED'", + }) + .matchHeader('login-customer-id', '1112223333') + .reply(200, { ...getManyResult, results: undefined }); + }); + + afterAll(() => googleAdsNock.done()); + + new NodeTestHarness().setupTests({ + credentials, + workflowFiles: ['getMany.workflow.json'], + }); + }); +}); diff --git a/packages/nodes-base/nodes/Google/Ads/__test__/node/fixtures/get.json b/packages/nodes-base/nodes/Google/Ads/__test__/node/fixtures/get.json new file mode 100644 index 0000000000..9511176e19 --- /dev/null +++ b/packages/nodes-base/nodes/Google/Ads/__test__/node/fixtures/get.json @@ -0,0 +1,27 @@ +{ + "results": [ + { + "campaign": { + "resourceName": "customers/5171368254/campaigns/22682295812", + "status": "ENABLED", + "advertisingChannelType": "SEARCH", + "name": "Search-1", + "id": "22682295812" + }, + "metrics": { + "videoViews": "0", + "conversions": 0, + "costMicros": "0", + "impressions": "0", + "interactions": "0" + }, + "campaignBudget": { + "resourceName": "customers/5171368254/campaignBudgets/14669466664", + "period": "DAILY", + "amountMicros": "10000000" + } + } + ], + "fieldMask": "campaign.id,campaign.name,campaignBudget.amountMicros,campaignBudget.period,campaign.status,campaign.optimizationScore,campaign.advertisingChannelType,campaign.advertisingChannelSubType,metrics.impressions,metrics.interactions,metrics.interactionRate,metrics.averageCost,metrics.costMicros,metrics.conversions,metrics.costPerConversion,metrics.conversionsFromInteractionsRate,metrics.videoViews,metrics.averageCpm,metrics.ctr", + "queryResourceConsumption": "596" +} diff --git a/packages/nodes-base/nodes/Google/Ads/__test__/node/fixtures/getMany.json b/packages/nodes-base/nodes/Google/Ads/__test__/node/fixtures/getMany.json new file mode 100644 index 0000000000..9f1e99312e --- /dev/null +++ b/packages/nodes-base/nodes/Google/Ads/__test__/node/fixtures/getMany.json @@ -0,0 +1,27 @@ +{ + "results": [ + { + "campaign": { + "resourceName": "customers/5171368254/campaigns/22682295812", + "status": "ENABLED", + "advertisingChannelType": "SEARCH", + "name": "Search-1", + "id": "22682295812" + }, + "metrics": { + "videoViews": "0", + "conversions": 0, + "costMicros": "0", + "impressions": "0", + "interactions": "0" + }, + "campaignBudget": { + "resourceName": "customers/5171368254/campaignBudgets/14669466664", + "period": "DAILY", + "amountMicros": "10000000" + } + } + ], + "fieldMask": "campaign.id,campaign.name,campaignBudget.amountMicros,campaignBudget.period,campaign.status,campaign.optimizationScore,campaign.advertisingChannelType,campaign.advertisingChannelSubType,metrics.impressions,metrics.interactions,metrics.interactionRate,metrics.averageCost,metrics.costMicros,metrics.conversions,metrics.costPerConversion,metrics.conversionsFromInteractionsRate,metrics.videoViews,metrics.averageCpm,metrics.ctr", + "queryResourceConsumption": "570" +} diff --git a/packages/nodes-base/nodes/Google/Ads/__test__/node/get.workflow.json b/packages/nodes-base/nodes/Google/Ads/__test__/node/get.workflow.json new file mode 100644 index 0000000000..d3d65df724 --- /dev/null +++ b/packages/nodes-base/nodes/Google/Ads/__test__/node/get.workflow.json @@ -0,0 +1,77 @@ +{ + "name": "Google Ads Get", + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [0, -160], + "id": "efd3f04e-8695-4f2c-8f8d-0b0166390d3f", + "name": "When clicking ‘Execute workflow’" + }, + { + "parameters": { + "operation": "get", + "managerCustomerId": "111-222-3333", + "clientCustomerId": "444-555-6666", + "campaignId": "12345678901", + "requestOptions": {} + }, + "type": "n8n-nodes-base.googleAds", + "typeVersion": 1, + "position": [220, -160], + "id": "773cca04-b4be-4bfd-8fb4-e37154df2991", + "name": "Get", + "credentials": { + "googleAdsOAuth2Api": { + "id": "VFEJAm9y8GDEsnS4", + "name": "Google Ads account" + } + } + } + ], + "pinData": { + "Get": [ + { + "json": { + "resourceName": "customers/5171368254/campaignBudgets/14669466664", + "status": "ENABLED", + "advertisingChannelType": "SEARCH", + "name": "Search-1", + "id": "22682295812", + "videoViews": "0", + "conversions": 0, + "costMicros": "0", + "impressions": "0", + "interactions": "0", + "period": "DAILY", + "amountMicros": "10000000" + } + } + ] + }, + "connections": { + "When clicking ‘Execute workflow’": { + "main": [ + [ + { + "node": "Get", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "b72b855a-9f8a-4872-9311-6e65940e85f1", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "e115be144a6a5547dbfca93e774dfffa178aa94a181854c13e2ce5e14d195b2e" + }, + "id": "Ffm7CA1AIhKGiOlK", + "tags": [] +} diff --git a/packages/nodes-base/nodes/Google/Ads/__test__/node/getMany.workflow.json b/packages/nodes-base/nodes/Google/Ads/__test__/node/getMany.workflow.json new file mode 100644 index 0000000000..c8e0f523f6 --- /dev/null +++ b/packages/nodes-base/nodes/Google/Ads/__test__/node/getMany.workflow.json @@ -0,0 +1,148 @@ +{ + "name": "Google Ads Get Many", + "nodes": [ + { + "parameters": {}, + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [0, 40], + "id": "efd3f04e-8695-4f2c-8f8d-0b0166390d3f", + "name": "When clicking ‘Execute workflow’" + }, + { + "parameters": { + "managerCustomerId": "111-222-3333", + "clientCustomerId": "444-555-6666", + "additionalOptions": {}, + "requestOptions": {} + }, + "type": "n8n-nodes-base.googleAds", + "typeVersion": 1, + "position": [220, -160], + "id": "773cca04-b4be-4bfd-8fb4-e37154df2991", + "name": "Get Many", + "credentials": { + "googleAdsOAuth2Api": { + "id": "VFEJAm9y8GDEsnS4", + "name": "Google Ads account" + } + } + }, + { + "parameters": { + "managerCustomerId": "111-222-3333", + "clientCustomerId": "444-555-6666", + "additionalOptions": { + "dateRange": "LAST_7_DAYS", + "campaignStatus": "ENABLED" + }, + "requestOptions": {} + }, + "type": "n8n-nodes-base.googleAds", + "typeVersion": 1, + "position": [220, 40], + "id": "3e913683-85bf-4295-98cd-2c8324d97094", + "name": "With Options", + "credentials": { + "googleAdsOAuth2Api": { + "id": "VFEJAm9y8GDEsnS4", + "name": "Google Ads account" + } + } + }, + { + "parameters": { + "managerCustomerId": "111-222-3333", + "clientCustomerId": "444-555-6666", + "additionalOptions": { + "campaignStatus": "REMOVED" + }, + "requestOptions": {} + }, + "type": "n8n-nodes-base.googleAds", + "typeVersion": 1, + "position": [220, 240], + "id": "7043d66a-a68c-495b-b6db-ffc8f1551065", + "name": "No Results", + "credentials": { + "googleAdsOAuth2Api": { + "id": "VFEJAm9y8GDEsnS4", + "name": "Google Ads account" + } + } + } + ], + "pinData": { + "Get Many": [ + { + "json": { + "resourceName": "customers/5171368254/campaignBudgets/14669466664", + "status": "ENABLED", + "advertisingChannelType": "SEARCH", + "name": "Search-1", + "id": "22682295812", + "videoViews": "0", + "conversions": 0, + "costMicros": "0", + "impressions": "0", + "interactions": "0", + "period": "DAILY", + "amountMicros": "10000000" + } + } + ], + "With Options": [ + { + "json": { + "resourceName": "customers/5171368254/campaignBudgets/14669466664", + "status": "ENABLED", + "advertisingChannelType": "SEARCH", + "name": "Search-1", + "id": "22682295812", + "videoViews": "0", + "conversions": 0, + "costMicros": "0", + "impressions": "0", + "interactions": "0", + "period": "DAILY", + "amountMicros": "10000000" + } + } + ], + "No Results": [] + }, + "connections": { + "When clicking ‘Execute workflow’": { + "main": [ + [ + { + "node": "Get Many", + "type": "main", + "index": 0 + }, + { + "node": "With Options", + "type": "main", + "index": 0 + }, + { + "node": "No Results", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "a77e4f29-8caa-4d3b-a7f9-9232c1234b93", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "e115be144a6a5547dbfca93e774dfffa178aa94a181854c13e2ce5e14d195b2e" + }, + "id": "Ffm7CA1AIhKGiOlK", + "tags": [] +}