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 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-v10.0.0-009688.svg?style=flat-square">
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/icons/logo.svg">
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/v10/CustomerService#listaccessiblecustomers). It returns the resource names of available customer accounts.
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
- hooks: { onQueryStart },
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
- hooks: { onQueryError },
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 mutation. 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.
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
- hooks: { onQueryEnd },
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/v10/GoogleAdsFailure).
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/v10/AccessInvitationErrorEnum.AccessInvitationError), as well as more information about [handling errors here](https://developers.google.com/google-ads/api/docs/best-practices/error-types).
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";
@@ -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
- var customer_1 = require("./customer");
41
- var service_1 = require("./service");
42
- var Client = /** @class */ (function () {
43
- function Client(options) {
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
- Client.prototype.Customer = function (customerOptions, hooks) {
47
- var cus = new customer_1.Customer(this.options, customerOptions, hooks);
10
+ Customer(customerOptions, hooks) {
11
+ const cus = new customer_1.Customer(this.options, customerOptions, hooks);
48
12
  return cus;
49
- };
50
- Client.prototype.listAccessibleCustomers = function (refreshToken) {
51
- return __awaiter(this, void 0, void 0, function () {
52
- var service, customerService, response, err_1;
53
- return __generator(this, function (_a) {
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
- return Client;
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;
@@ -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