Google Ads API
Unofficial Google Ads API client library for Node.js
- Simple and easy to use API
- Uses gRPC and Protocol Buffers internally (recommended by Google)
- Typescript definitions for all resources, enums, errors and services
- Provides all API functionality
The Google Ads API is the new replacement to the AdWords API. Google will deprecate the AdWords API sometime in 2020.
npm install google-ads-api
Note: Our documentation site is currently outdated (an older version of this library and the Google Ads API) but is still up. We're working on updating these docs soon.
For now we recommend following the usage examples below.
- Setup
- Reporting
- Mutations
- Misc
import { GoogleAdsApi } from "google-ads-api";
const client = new GoogleAdsApi({
client_id: "<CLIENT-ID>",
client_secret: "<CLIENT-SECRET>",
developer_token: "<DEVELOPER-TOKEN>",
});
const customer = client.Customer({
customer_id: "1234567890",
refresh_token: "<REFRESH-TOKEN>",
});
// Also supports login & linked customer ids
const customer = client.Customer({
customer_id: "1234567890",
login_customer_id: "<LOGIN-CUSTOMER-ID>",
linked_customer_id: "<LINKED-CUSTOMER-ID>",
refresh_token: "<REFRESH-TOKEN>",
});
This is a special client method for listing the accessible customers for a given refresh token, and is equivalent to CustomerService.listAccessibleCustomers. It returns the resource names of available customer accounts.
const client = new GoogleAdsApi({
client_id: "<CLIENT-ID>",
client_secret: "<CLIENT-SECRET>",
developer_token: "<DEVELOPER-TOKEN>",
});
const refreshToken = "<REFRESH-TOKEN">
const customers = await client.listAccessibleCustomers(refreshToken);
import { enums } from "google-ads-api";
const campaigns = await customer.report({
entity: "campaign",
attributes: [
"campaign.id",
"campaign.name",
"campaign.bidding_strategy_type",
"campaign_budget.amount_micros",
],
metrics: [
"metrics.cost_micros",
"metrics.clicks",
"metric.impressions",
"metrics.all_conversions",
],
constraints: {
"campaign.status": enums.CampaignStatus.ENABLED,
},
limit: 20,
});
If you prefer to use the Google Ads Query Language (GAQL) the query
method is available. Internally report
uses this function. More GAQL examples can be found here.
const campaigns = await customer.query(`
SELECT
campaign.id,
campaign.name,
campaign.bidding_strategy_type,
campaign_budget.amount_micros,
metrics.cost_micros,
metrics.clicks,
metric.impressions,
metrics.all_conversions,
FROM
campaign
WHERE
campaign.status = "ENABLED"
LIMIT 20
`);
import { enums } from "google-ads-api";
const campaigns = await customer.report({
entity: "ad_group",
metrics: [
"metrics.cost_micros",
"metrics.clicks",
"metric.impressions",
"metrics.all_conversions",
],
segments: ["segments.date"],
from_date: "2021-01-01",
to_date: "2021-02-01",
});
Streaming is useful when you're dealing with >10k rows, as this is the page size for results.
import { enums } from "google-ads-api";
const stream = customer.reportStream({
entity: "ad_group_criterion",
attributes: [
"ad_group_criterion.keyword.text",
"ad_group_criterion.status",
],
constraints: {
"ad_group_criterion.type": enums.CriterionType.KEYWORD,
},
});
// Rows are streamed in one by one
for await (const row of stream) {
// Break the loop to stop streaming
if(someLogic) {
break
}
}
import { resources, enums, ResourceNames } from "google-ads-api";
const ad = new resources.Ad({
expanded_text_ad: {
headline_part1: "Cruise to Mars",
headline_part2: "Best Space Cruise Line",
description: "Buy your tickets now!",
path1: "cruises",
path2: "mars",
},
final_urls: ["https://example.com"],
type: enums.AdType.EXPANDED_TEXT_AD,
});
const adGroup = ResourceNames.adGroup(cus.credentials.customerId, "123");
const adGroupAd = new resources.AdGroupAd({
status: enums.AdGroupAdStatus.PAUSED,
ad_group,
ad,
});
// Returns an array of newly created resource names if successful
const { results } = await cus.adGroupAds.create([adGroupAd]);
If a summary row is requested in the report
method, it will be included as the first row of the results.
const [summaryRow, ...response] = await customer.report({
entity: "campaign",
metrics: ["metrics.clicks", "metrics.all_conversions"],
summary_row_setting: enums.SummaryRowSetting.SUMMARY_ROW_WITH_RESULTS,
});
If a summery row is requested in the reportStream
method, it will be included as the final iterated row of the results.
const stream = customer.reportStream({
entity: "campaign",
metrics: ["metrics.clicks", "metrics.all_conversions"],
summary_row_setting: enums.SummaryRowSetting.SUMMARY_ROW_WITH_RESULTS,
});
const accumulator = [];
for await (const row of stream) {
accumulator.push(row);
}
const summaryRow = accumulator.slice(-1)[0];
The reportCount
method acts like report
but returns the total number of rows that the query would have returned (ignoring the limit). This replaces the return_total_results_count
report option.
const totalRows = await customer.reportCount({
entity: "search_term_view",
attributes: ["search_term_view.resource_name"],
})
The library provides a set of helper methods under the ResourceNames
export. These are used for compiling resource names from ids. Arguments can be of the type string
, number
, or a mix of both. If you have a client.Customer
instance available, you can get the customer id with customer.credentials.customerId
.
import { ResourceNames } from "google-ads-api";
const customerId = "1234567890";
const campaignId = "3218318373";
ResourceNames.campaign(customerId, campaignId);
// "customers/1234567890/campaigns/3218318373"
ResourceNames.adGroup(123, 123);
// "customers/123/adGroups/123"
ResourceNames.adGroupAd("1", "2", "3");
// "customers/1/adGroupAds/2~3"
const amsterdamLocationId = 1010543;
ResourceNames.geoTargetConstant(amsterdam);
// "geoTargetConstants/1010543"
ResourceNames.accountBudget(customer.credentials.customer_id, 123);
// "customers/1234567890/accountBudgets/123"
The library provides hooks that can be executed before, after or on error of a query or a mutation. Query hooks have access to the gaql query and the reportOptions, while mutation hooks have access to the mutations.
const customer = client.Customer({
clientOptions,
customerOptions,
hooks: {
onQueryStart({ credentials, query, reportOptions, cancel, editOptions }) {
if (reportOptions.entity === "campaign") {
cancel([]); // cancels the query and returns the given argument
}
if (env.mode === "dev") {
editOptions({ validate_only: true }); // edits the request options
}
},
onQueryError({ credentials, query, reportOptions, error }) {
console.log(error);
},
onQueryEnd({ credentials, query, reportOptions, response, resolve }) {
resolve(response.slice(0, 5)); // resolves the query with the given argument
},
onMutationStart({ credentials, mutations, cancel }) {
if (mutations.length === 0) {
cancel({}); // cancels the mutation and returns the given argument
}
if (env.mode === "dev") {
editOptions({ validate_only: true }); // edits the mutate options
}
},
onMutationError({ credentials, mutations, error }) {
console.log(error);
},
onMutationEnd({ credentials, mutations, response, resolve }) {
if (reponse.partial_failure_error) {
resolve({}); // resolves the mutation with the given argument
}
},
},
});