google-ads-api 10.0.1 → 11.1.0
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.
- package/README.md +80 -23
- package/build/src/client.js +31 -80
- package/build/src/customer.d.ts +10 -0
- package/build/src/customer.js +313 -472
- package/build/src/hooks.d.ts +38 -3
- package/build/src/index.d.ts +1 -1
- package/build/src/index.js +5 -1
- package/build/src/parser.js +29 -36
- package/build/src/protos/autogen/enums.d.ts +514 -300
- package/build/src/protos/autogen/enums.js +805 -583
- package/build/src/protos/autogen/fields.d.ts +172 -153
- package/build/src/protos/autogen/fields.js +12 -1
- package/build/src/protos/autogen/resourceNames.d.ts +16 -0
- package/build/src/protos/autogen/resourceNames.js +177 -157
- package/build/src/protos/autogen/serviceFactory.d.ts +197 -147
- package/build/src/protos/autogen/serviceFactory.js +18483 -17447
- package/build/src/protos/index.d.ts +6 -6
- package/build/src/protos/index.js +7 -7
- package/build/src/query.js +74 -81
- package/build/src/service.js +107 -112
- package/build/src/testUtils.js +52 -53
- package/build/src/utils.js +19 -21
- package/build/src/version.d.ts +1 -1
- package/build/src/version.js +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
</p>
|
|
8
8
|
<p align="center">
|
|
9
9
|
<a href="https://developers.google.com/google-ads/api/docs/release-notes">
|
|
10
|
-
<img src="https://img.shields.io/badge/google%20ads-
|
|
10
|
+
<img src="https://img.shields.io/badge/google%20ads-v11.1.0-009688.svg?style=flat-square">
|
|
11
11
|
</a>
|
|
12
12
|
<a href="https://www.npmjs.com/package/google-ads-api">
|
|
13
13
|
<img src="https://img.shields.io/npm/v/google-ads-api.svg?style=flat-square">
|
|
@@ -15,14 +15,11 @@
|
|
|
15
15
|
<a>
|
|
16
16
|
<img src="https://img.shields.io/npm/dm/google-ads-api.svg?style=flat-square">
|
|
17
17
|
</a>
|
|
18
|
-
<a>
|
|
19
|
-
<img src="https://img.shields.io/david/opteo/google-ads-api.svg?style=flat-square">
|
|
20
|
-
</a>
|
|
21
18
|
</p>
|
|
22
19
|
|
|
23
20
|
<p align="center">
|
|
24
21
|
<a href="https://opteo.com">
|
|
25
|
-
<img src="https://app.opteo.com/
|
|
22
|
+
<img src="https://app.opteo.com/favicon.png" width="90" height="90">
|
|
26
23
|
</a>
|
|
27
24
|
</p>
|
|
28
25
|
|
|
@@ -102,7 +99,7 @@ const customer = client.Customer({
|
|
|
102
99
|
|
|
103
100
|
## List accessible customers
|
|
104
101
|
|
|
105
|
-
This is a special client method for listing the accessible customers for a given refresh token, and is equivalent to [CustomerService.listAccessibleCustomers](https://developers.google.com/google-ads/api/reference/rpc/
|
|
102
|
+
This is a special client method for listing the accessible customers for a given refresh token, and is equivalent to [CustomerService.listAccessibleCustomers](https://developers.google.com/google-ads/api/reference/rpc/v11/CustomerService#listaccessiblecustomers). It returns the resource names of available customer accounts.
|
|
106
103
|
|
|
107
104
|
```ts
|
|
108
105
|
const client = new GoogleAdsApi({
|
|
@@ -111,7 +108,7 @@ const client = new GoogleAdsApi({
|
|
|
111
108
|
developer_token: "<DEVELOPER-TOKEN>",
|
|
112
109
|
});
|
|
113
110
|
|
|
114
|
-
const refreshToken = "<REFRESH-TOKEN"
|
|
111
|
+
const refreshToken = "<REFRESH-TOKEN>";
|
|
115
112
|
|
|
116
113
|
const customers = await client.listAccessibleCustomers(refreshToken);
|
|
117
114
|
```
|
|
@@ -160,7 +157,7 @@ const campaigns = await customer.query(`
|
|
|
160
157
|
metrics.cost_micros,
|
|
161
158
|
metrics.clicks,
|
|
162
159
|
metrics.impressions,
|
|
163
|
-
metrics.all_conversions
|
|
160
|
+
metrics.all_conversions
|
|
164
161
|
FROM
|
|
165
162
|
campaign
|
|
166
163
|
WHERE
|
|
@@ -197,7 +194,6 @@ const campaigns = await customer.report({
|
|
|
197
194
|
Calls searchStream internally but returns the rows one by one in an async iterator.
|
|
198
195
|
|
|
199
196
|
<!-- prettier-ignore-start -->
|
|
200
|
-
|
|
201
197
|
```ts
|
|
202
198
|
import { enums } from "google-ads-api";
|
|
203
199
|
|
|
@@ -222,6 +218,30 @@ for await (const row of stream) {
|
|
|
222
218
|
```
|
|
223
219
|
<!-- prettier-ignore-end -->
|
|
224
220
|
|
|
221
|
+
Or use a GAQL query.
|
|
222
|
+
|
|
223
|
+
<!-- prettier-ignore-start -->
|
|
224
|
+
```ts
|
|
225
|
+
const stream = customer.queryStream(`
|
|
226
|
+
SELECT
|
|
227
|
+
ad_group_criterion.keyword.text,
|
|
228
|
+
ad_group_criterion.status
|
|
229
|
+
FROM
|
|
230
|
+
ad_group_criterion
|
|
231
|
+
WHERE
|
|
232
|
+
ad_group_criterion.type = "KEYWORD"
|
|
233
|
+
`);
|
|
234
|
+
|
|
235
|
+
// Rows are streamed in one by one
|
|
236
|
+
for await (const row of stream) {
|
|
237
|
+
// Break the loop to stop streaming
|
|
238
|
+
if (someLogic) {
|
|
239
|
+
break
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
```
|
|
243
|
+
<!-- prettier-ignore-end -->
|
|
244
|
+
|
|
225
245
|
---
|
|
226
246
|
|
|
227
247
|
## Retrieve Keywords with a raw stream
|
|
@@ -353,6 +373,27 @@ const result = await customer.mutateResources(operations);
|
|
|
353
373
|
|
|
354
374
|
---
|
|
355
375
|
|
|
376
|
+
## Uploading Click Conversions
|
|
377
|
+
|
|
378
|
+
```ts
|
|
379
|
+
const clickConversion = {
|
|
380
|
+
gclid: "<GOOGLE-CLICK-ID>",
|
|
381
|
+
conversion_action: "customers/1234567890/conversionActions/111222333",
|
|
382
|
+
conversion_date_time: "2022-01-11 00:00:00",
|
|
383
|
+
conversion_value: 123,
|
|
384
|
+
currency_code: "GBP",
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
const request = new services.UploadClickConversionsRequest({
|
|
388
|
+
customer_id: customerId,
|
|
389
|
+
conversions: [clickConversion],
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
await customer.conversionUploads.uploadClickConversions(request);
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
356
397
|
## Summary Row
|
|
357
398
|
|
|
358
399
|
If a summary row is requested in the `report` method, it will be included as the **first** row of the results.
|
|
@@ -487,13 +528,24 @@ These hooks have access to the `customerCredentials` argument, containing the `c
|
|
|
487
528
|
|
|
488
529
|
These hooks also have access to the `method` argument, containing the mutation method as a string.
|
|
489
530
|
|
|
531
|
+
### Service hooks:
|
|
532
|
+
|
|
533
|
+
- `onServiceStart`
|
|
534
|
+
- `onServiceError`
|
|
535
|
+
- `onServiceEnd`
|
|
536
|
+
|
|
537
|
+
These hooks have access to the `customerCredentials` argument, containing the `customer_id`, `login_customer_id` and `linked_customer_id`.
|
|
538
|
+
|
|
539
|
+
These hooks also have access to the `method` argument, containing the mutation method as a string.
|
|
540
|
+
|
|
490
541
|
### Pre-request hooks:
|
|
491
542
|
|
|
492
543
|
- `onQueryStart` - `query` and `report`
|
|
493
544
|
- `onStreamStart` - `reportStream` and `reportStreamRaw`
|
|
494
545
|
- `onMutationStart`
|
|
546
|
+
- `onServiceStart`
|
|
495
547
|
|
|
496
|
-
These hooks are executed **before** a query/stream/mutation.
|
|
548
|
+
These hooks are executed **before** a query/stream/mutation/service.
|
|
497
549
|
|
|
498
550
|
These hooks have access to the `cancel` method, which can cancel the action before it is done. The query and mutation pre-request hooks allow an optional argument to be passed into the `cancel` method, which will be used as an alternative return value for the query/mutation. A good use case for this method would be to cancel with a cached result.
|
|
499
551
|
|
|
@@ -513,9 +565,10 @@ const onQueryStart: OnQueryStart = async ({ cancel, editOptions }) => {
|
|
|
513
565
|
|
|
514
566
|
const customer = client.Customer({
|
|
515
567
|
clientOptions,
|
|
516
|
-
customerOptions
|
|
517
|
-
|
|
518
|
-
}
|
|
568
|
+
customerOptions
|
|
569
|
+
},
|
|
570
|
+
{ onQueryStart }
|
|
571
|
+
);
|
|
519
572
|
```
|
|
520
573
|
|
|
521
574
|
### On error hooks:
|
|
@@ -523,8 +576,9 @@ const customer = client.Customer({
|
|
|
523
576
|
- `onQueryError` - `query` and `report`
|
|
524
577
|
- `onStreamError` - `reportStream` (but **not** `reportStreamRaw`)
|
|
525
578
|
- `onMutationError`
|
|
579
|
+
- `onServiceStart`
|
|
526
580
|
|
|
527
|
-
These hooks are executed when a query/stream/mutation throws an error. If the error is a Google Ads failure then it will be converted to a `GoogleAdsFailure` first. The error can be accessed in these hooks with the `error` argument. Note that the `onStreamError` hook will not work with the `reportStreamRaw` method to avoid blocking the thread.
|
|
581
|
+
These hooks are executed when a query/stream/mutation/service throws an error. If the error is a Google Ads failure then it will be converted to a `GoogleAdsFailure` first. The error can be accessed in these hooks with the `error` argument. Note that the `onStreamError` hook will not work with the `reportStreamRaw` method to avoid blocking the thread.
|
|
528
582
|
|
|
529
583
|
```ts
|
|
530
584
|
import { OnQueryError } from "google-ads-api";
|
|
@@ -535,17 +589,19 @@ const onQueryError: OnQueryError = async ({ error }) => {
|
|
|
535
589
|
|
|
536
590
|
const customer = client.Customer({
|
|
537
591
|
clientOptions,
|
|
538
|
-
customerOptions
|
|
539
|
-
|
|
540
|
-
}
|
|
592
|
+
customerOptions
|
|
593
|
+
},
|
|
594
|
+
{ onQueryError }
|
|
595
|
+
);
|
|
541
596
|
```
|
|
542
597
|
|
|
543
598
|
### Post-request hooks:
|
|
544
599
|
|
|
545
600
|
- `onQueryEnd` - `query` and `report`
|
|
546
601
|
- `onMutationEnd`
|
|
602
|
+
- `onServiceEnd`
|
|
547
603
|
|
|
548
|
-
These hooks are executed **after** a query or
|
|
604
|
+
These hooks are executed **after** a query, mutation or service. This library does not contain an `onStreamEnd` hook to avoid accumulating the results of streams, and also so that we don't block the thread by waiting for the end event to be emitted.
|
|
549
605
|
|
|
550
606
|
```ts
|
|
551
607
|
import { OnQueryEnd } from "google-ads-api";
|
|
@@ -557,18 +613,19 @@ const onQueryEnd: OnQueryEnd = async ({ response, resolve }) => {
|
|
|
557
613
|
|
|
558
614
|
const customer = client.Customer({
|
|
559
615
|
clientOptions,
|
|
560
|
-
customerOptions
|
|
561
|
-
|
|
562
|
-
}
|
|
616
|
+
customerOptions
|
|
617
|
+
},
|
|
618
|
+
{ onQueryEnd }
|
|
619
|
+
);
|
|
563
620
|
```
|
|
564
621
|
|
|
565
622
|
---
|
|
566
623
|
|
|
567
624
|
## Error handling
|
|
568
625
|
|
|
569
|
-
All errors, apart from GRPC specific cases (such as a connection problem or timeout, [see more here](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md)), are instances of a [GoogleAdsFailure](https://developers.google.com/google-ads/api/reference/rpc/
|
|
626
|
+
All errors, apart from GRPC specific cases (such as a connection problem or timeout, [see more here](https://github.com/grpc/grpc/blob/master/doc/statuscodes.md)), are instances of a [GoogleAdsFailure](https://developers.google.com/google-ads/api/reference/rpc/v11/GoogleAdsFailure).
|
|
570
627
|
|
|
571
|
-
You can find a list of all error types for a specific version in [the official documentation](https://developers.google.com/google-ads/api/reference/rpc/
|
|
628
|
+
You can find a list of all error types for a specific version in [the official documentation](https://developers.google.com/google-ads/api/reference/rpc/v11/AccessInvitationErrorEnum.AccessInvitationError), as well as more information about [handling errors here](https://developers.google.com/google-ads/api/docs/best-practices/error-types).
|
|
572
629
|
|
|
573
630
|
```ts
|
|
574
631
|
import { errors } from "google-ads-api";
|
package/build/src/client.js
CHANGED
|
@@ -1,88 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
18
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.Client = void 0;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
4
|
+
const customer_1 = require("./customer");
|
|
5
|
+
const service_1 = require("./service");
|
|
6
|
+
class Client {
|
|
7
|
+
constructor(options) {
|
|
44
8
|
this.options = options;
|
|
45
9
|
}
|
|
46
|
-
|
|
47
|
-
|
|
10
|
+
Customer(customerOptions, hooks) {
|
|
11
|
+
const cus = new customer_1.Customer(this.options, customerOptions, hooks);
|
|
48
12
|
return cus;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
switch (_a.label) {
|
|
55
|
-
case 0:
|
|
56
|
-
service = new service_1.Service(this.options, {
|
|
57
|
-
customer_id: "",
|
|
58
|
-
refresh_token: refreshToken,
|
|
59
|
-
});
|
|
60
|
-
return [4 /*yield*/, service.loadService("CustomerServiceClient")];
|
|
61
|
-
case 1:
|
|
62
|
-
customerService = _a.sent();
|
|
63
|
-
_a.label = 2;
|
|
64
|
-
case 2:
|
|
65
|
-
_a.trys.push([2, 4, , 5]);
|
|
66
|
-
return [4 /*yield*/, customerService.listAccessibleCustomers({}, {
|
|
67
|
-
// @ts-expect-error Field not included in type definitions
|
|
68
|
-
otherArgs: {
|
|
69
|
-
// @ts-expect-error Protected usage is fine here
|
|
70
|
-
headers: service.callHeaders,
|
|
71
|
-
},
|
|
72
|
-
})];
|
|
73
|
-
case 3:
|
|
74
|
-
response = (_a.sent())[0];
|
|
75
|
-
return [2 /*return*/, response];
|
|
76
|
-
case 4:
|
|
77
|
-
err_1 = _a.sent();
|
|
78
|
-
console.log(err_1);
|
|
79
|
-
// @ts-expect-error Protected usage is fine here
|
|
80
|
-
throw service.getGoogleAdsError(err_1);
|
|
81
|
-
case 5: return [2 /*return*/];
|
|
82
|
-
}
|
|
83
|
-
});
|
|
13
|
+
}
|
|
14
|
+
async listAccessibleCustomers(refreshToken) {
|
|
15
|
+
const service = new service_1.Service(this.options, {
|
|
16
|
+
customer_id: "",
|
|
17
|
+
refresh_token: refreshToken,
|
|
84
18
|
});
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
19
|
+
// @ts-expect-error Protected usage is fine here
|
|
20
|
+
const customerService = await service.loadService("CustomerServiceClient");
|
|
21
|
+
try {
|
|
22
|
+
// @ts-expect-error Type definition is incorrect, response is an array
|
|
23
|
+
const [response] = await customerService.listAccessibleCustomers({}, {
|
|
24
|
+
// @ts-expect-error Field not included in type definitions
|
|
25
|
+
otherArgs: {
|
|
26
|
+
// @ts-expect-error Protected usage is fine here
|
|
27
|
+
headers: service.callHeaders,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
return response;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.log(err);
|
|
34
|
+
// @ts-expect-error Protected usage is fine here
|
|
35
|
+
throw service.getGoogleAdsError(err);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
88
39
|
exports.Client = Client;
|
package/build/src/customer.d.ts
CHANGED
|
@@ -11,6 +11,15 @@ export declare class Customer extends ServiceFactory {
|
|
|
11
11
|
@hooks onQueryStart, onQueryError, onQueryEnd
|
|
12
12
|
*/
|
|
13
13
|
query<T = services.IGoogleAdsRow[]>(gaqlQuery: string, requestOptions?: RequestOptions): Promise<T>;
|
|
14
|
+
/**
|
|
15
|
+
@description Stream query using a raw GAQL string. If a generic type is provided, it must be the type of a single row.
|
|
16
|
+
If a summary row is requested then this will be the last emitted row of the stream.
|
|
17
|
+
@hooks onStreamStart, onStreamError
|
|
18
|
+
@example
|
|
19
|
+
const stream = queryStream<T>(gaqlQuery)
|
|
20
|
+
for await (const row of stream) { ... }
|
|
21
|
+
*/
|
|
22
|
+
queryStream<T = services.IGoogleAdsRow>(gaqlQuery: string, requestOptions?: RequestOptions): AsyncGenerator<T>;
|
|
14
23
|
/**
|
|
15
24
|
@description Single query using ReportOptions.
|
|
16
25
|
If a summary row is requested then this will be the first row of the results.
|
|
@@ -44,6 +53,7 @@ export declare class Customer extends ServiceFactory {
|
|
|
44
53
|
private search;
|
|
45
54
|
private paginatedSearch;
|
|
46
55
|
private querier;
|
|
56
|
+
private streamer;
|
|
47
57
|
/**
|
|
48
58
|
* @description Creates, updates, or removes resources. This method supports atomic transactions
|
|
49
59
|
* with multiple types of resources. For example, you can atomically create a campaign and a
|