{"id":15573136,"url":"https://github.com/htdangkhoa/google-ads","last_synced_at":"2026-03-10T07:05:08.371Z","repository":{"id":65440627,"uuid":"586157696","full_name":"htdangkhoa/google-ads","owner":"htdangkhoa","description":"(Unofficial) Google Ads API Nodejs Client Library","archived":false,"fork":false,"pushed_at":"2025-10-16T07:02:53.000Z","size":513,"stargazers_count":13,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-17T07:09:26.206Z","etag":null,"topics":["cjs","commonjs","esm","esmodules","google","google-ads","google-ads-api","google-api","grpc","nodejs","protobuf","sdk","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/@htdangkhoa/google-ads","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/htdangkhoa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-01-07T06:08:47.000Z","updated_at":"2025-10-17T06:59:24.000Z","dependencies_parsed_at":"2024-03-27T12:25:54.340Z","dependency_job_id":"965c5413-7ac1-4669-99f6-0a990f3277e6","html_url":"https://github.com/htdangkhoa/google-ads","commit_stats":{"total_commits":164,"total_committers":2,"mean_commits":82.0,"dds":"0.12195121951219512","last_synced_commit":"9d5b5f20f6b1649d2d85e067b536e7fa36cf8b18"},"previous_names":[],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/htdangkhoa/google-ads","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Fgoogle-ads","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Fgoogle-ads/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Fgoogle-ads/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Fgoogle-ads/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/htdangkhoa","download_url":"https://codeload.github.com/htdangkhoa/google-ads/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htdangkhoa%2Fgoogle-ads/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30326893,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cjs","commonjs","esm","esmodules","google","google-ads","google-ads-api","google-api","grpc","nodejs","protobuf","sdk","typescript"],"created_at":"2024-10-02T18:10:45.388Z","updated_at":"2026-03-10T07:05:08.363Z","avatar_url":"https://github.com/htdangkhoa.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eGoogle Ads API Nodejs Client Library\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://developers.google.com/google-ads/api/docs/release-notes#v23-2026-01-28\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/google%20ads-v23%202026--01--28-009688.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@htdangkhoa/google-ads\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/@htdangkhoa/google-ads.svg?style=flat-square\"\u003e\n  \u003c/a\u003e\n  \u003ca href='https://coveralls.io/github/htdangkhoa/google-ads'\u003e\n    \u003cimg src='https://img.shields.io/coverallsCoverage/github/htdangkhoa/google-ads?style=flat-square' alt='Coverage Status' /\u003e\n  \u003c/a\u003e\n  \u003ca href='https://depfu.com/github/htdangkhoa/google-ads?project_id=40063'\u003e\n    \u003cimg src='https://badges.depfu.com/badges/b81badee90e335b411e120d083f3c154/count.svg' alt='depfu' /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Usage\n\n### Authentication\n\n```ts\nimport { UserRefreshClient, JWT } from 'google-auth-library';\n\n// for web application\nconst authClient = new UserRefreshClient({\n  clientId: '\u003cCLIENT_ID\u003e',\n  clientSecret: '\u003cCLIENT_SECRET\u003e',\n  refreshToken: '\u003cREFRESH_TOKEN\u003e',\n});\n\n// or use JWT for service account\nconst authClient = new JWT({\n  keyFile: '\u003cKEY_FILE\u003e',\n  subject: '\u003cGOOGLE_ADS_EMAIL\u003e',\n  scopes: ['https://www.googleapis.com/auth/adwords'],\n});\n```\n\n### Customer\n\n```ts\nimport { Customer } from '@htdangkhoa/google-ads';\n\nconst service = new Customer({\n  auth: authClient,\n  developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n});\n\nconst { resource_names: customers } = await service.listAccessibleCustomers();\n\n// ...\n```\n\n### Search\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n  },\n  {\n    customer_id: '\u003cCUSTOMER_ID\u003e',\n  },\n);\n\nconst customerClients = await service.search({\n  query: `\n    SELECT\n      customer_client.descriptive_name,\n      customer_client.resource_name,\n      customer_client.client_customer,\n      customer_client.level,\n      customer_client.manager\n    FROM customer_client\n  `,\n});\n\n// ...\n```\n\n### Search stream\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n  }, {\n    customer_id: '\u003cMANAGER_ID\u003e',\n  }\n);\n\nconst response = service\n  .setCustomerId('\u003cCUSTOMER_ID\u003e') // you can switch customer id\n  .setLoginCustomerId('\u003cMANAGER_ID\u003e')\n  .searchStream({\n    query: `\n      SELECT\n        campaign.id,\n        campaign.name,\n        campaign.status\n      FROM campaign\n    `,\n  });\n\nfor await (const { results } of response) {\n  // ...\n}\n```\n\n### Campaign\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n  },\n  {\n    customer_id: '\u003cCUSTOMER_CLIENT_ID\u003e',\n    login_customer_id: '\u003cCUSTOMER_ID\u003e',\n  },\n);\n\nconst campaigns = await service.search({\n  query: `\n    SELECT\n      campaign.id,\n      campaign.name,\n      campaign.status\n    FROM campaign\n  `,\n});\n\n// ...\n```\n\n### Mutate\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n  },\n  {\n    customer_id: '\u003cCUSTOMER_CLIENT_ID\u003e',\n    login_customer_id: '\u003cCUSTOMER_ID\u003e',\n  },\n);\n\nconst response = await service.mutate({\n  mutate_operations: [\n    {\n      campaign_operation: {\n        create: {\n          // ...\n        },\n        update: {\n          // ...\n        },\n        remove: '\u003cCAMPAIGN_RESOURCE_NAME\u003e',\n      },\n    },\n  ],\n  partial_failure: true,\n});\n\n// ...\n```\n\n### Query Builder\n\n```ts\nimport { QueryBuilder } from '@htdangkhoa/google-ads';\n\nconst query = new QueryBuilder()\n  .select(\n    'campaign.id',\n    'campaign.name',\n    'segments.device',\n    'metrics.clicks',\n  )\n  .from('campaign')\n  .where(\n    {\n      attribute: 'metrics.impressions',\n      operator: Operators.GREATER_THAN,\n      value: \"0\",\n    },\n    {\n      attribute: 'segments.device',\n      operator: Operators.EQUALS,\n      value: \"MOBILE\",\n    },\n    {\n      attribute: 'segments.date',\n      operator: Operators.DURING,\n      value: Functions.LAST_30_DAYS,\n    },\n  )\n  .orderBy(\n    {\n      attribute: 'metrics.clicks',\n      direction: Order.DESC,\n    },\n  )\n  .limit(10)\n  .build();\n\nconst response = await service.search({ query });\n```\n\n## Logging\n\nRequests are logged with a one line summary and the full request/response body and headers.\n\n| Log type | Log name                        | Success level | Failure level |\n|----------|---------------------------------|---------------|---------------|\n| SUMMARY  | Google::Ads::GoogleAds::Summary | INFO          | WARN          |\n| DETAIL   | Google::Ads::GoogleAds::Detail  | DEBUG         | INFO          |\n\n### Basic\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n    logging: true,\n  },\n  {\n    customer_id: '\u003cCUSTOMER_ID\u003e',\n  },\n);\n```\n\n### Specific Log Type (SUMMARY or DETAIL)\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n    logging: {\n      summary: true,\n      detail: false,\n    },\n  },\n  {\n    customer_id: '\u003cCUSTOMER_ID\u003e',\n  },\n);\n```\n\n## gRPC Client Options\n\nThe `ServiceOptions` is extended from `@grpc/grpc-js` [ClientOptions](https://grpc.github.io/grpc/node/grpc.Client.html#~ClientOptions:~:text=to%20the%20server-,options,-Object), so you can pass any options you want to the client.\n\n```ts\nimport { GoogleAds } from '@htdangkhoa/google-ads';\n\nconst service = new GoogleAds(\n  {\n    auth: authClient,\n    developer_token: '\u003cDEVELOPER_TOKEN\u003e',\n    logging: {\n      summary: true,\n      detail: false,\n    },\n    interceptors: [\n      // your interceptors\n    ],\n  },\n  {\n    customer_id: '\u003cCUSTOMER_ID\u003e',\n  },\n);\n```\n\n## Interceptors\n\nSee more at [Node.js gRPC Library](https://grpc.github.io/grpc/node/module-src_client_interceptors.html) and some examples [here](https://github.com/grpc/proposal/blob/master/L5-node-client-interceptors.md).\n\n## Development\n\n\u003e [!WARNING]  \n\u003e This library is using `ts-proto` to generate the gRPC client. Since v2, `ts-proto` has changed the way to encode the request for image upload. Don't migrate to `ts-proto` v2 or higher until the issue is fixed.\n\n### Prerequisites\n\n- Protocol Buffer Compiler (protoc) version 3.0.0 or greater. The latest version can be downloaded from [here](https://grpc.io/docs/protoc-installation/)\n- Node.js version 16 or greater (LTS recommended) and npm version 8 or greater. The latest version of Node.js can be downloaded from [here](https://nodejs.org/en/download/)\n\n### Building\n\n1. Install dependencies\n\n    ```sh\n    yarn install\n    ```\n\n2. Pull in the new protos and compile them\n\n    ```sh\n    yarn generate \u003cGOOGLE_ADS_API_VERSION\u003e\n\n    # example\n    yarn generate v23\n    ```\n3. Make sure the version number in the `src` folder is correct (it should match the version number you passed to the `generate` command)\n\n4. Run tests to make sure everything worked (you may need to update the version numbers here)\n\n    ```sh\n    yarn test\n    ```\n\n5. Build the library\n\n    ```sh\n    yarn build\n    ```\n\n6. Make a pull request, get it approved and merged into `main`\n\n## Known Issues\n\n- With `ImageAsset`, you might get an error if you provide it as either `Uint8Array` or `Buffer`. The root cause is that the proto is `bytes` but the generator is generating to `Buffer/Uint8Array` which is the wrong type ([#166](https://github.com/htdangkhoa/google-ads/issues/166#issuecomment-2851472905)). The solution is to convert it to base64 string as shown below:\n\n  ```ts\n  const imageAsset = ImageAsset.create({\n    // @ts-expect-error\n    data: Buffer.from(asset.file.buffer).toString('base64'),\n  });\n\n  // or\n\n  const imageAsset: ImageAsset = {\n    // @ts-expect-error\n    data: Buffer.from(asset.file.buffer).toString('base64'),\n  };\n  ```\n  Reference: https://developers.google.com/google-ads/api/rest/reference/rest/latest/Asset#imageasset\n\n## License\nThe code in this project is released under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtdangkhoa%2Fgoogle-ads","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhtdangkhoa%2Fgoogle-ads","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtdangkhoa%2Fgoogle-ads/lists"}