npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

google-ads-api-client

v1.1.3

Published

A friendly and exhaustive client to the google-ads-api, code generated directly from google's published protobuf schema.

Downloads

14

Readme

google-ads-api-client

ci_on_commit deploy_on_tag

A friendly and exhaustive client to the google-ads-api, code generated directly from google's published protobuf schema.

overview

this package is a thin utility making it easy to use the grpc endpoints that google exposes for their google ads api.

this package:

  • code-generates the types + clients specified by google's protobuf schema of their api
  • exposes a simple way to use the code-generated clients

the benefits:

  • ✨ up to date - code generated from google's published protobuf definition of their api, ensuring its always up to date
  • 🔥 exhaustive - all services and methods that google has published are exposed through this library, no api left behind
  • 🚀 easy to use - documented, commented, and discoverable - making it easy to interact with their api
  • 🙂 helpful - goes out of the way to keep you in a pit of success

usage

install

npm install --save google-ads-api-client

examples

listing accessible customer ids

The google ads api requires you to specify which of your accessible google-ads-accounts (i.e., customers) you want to manage in a given api call. In order to specify them, you may first need to list the accessible ones.

import {
  getAuthenticatedGoogleAdsApiGrpcTransport,
  KeywordPlanIdeaServiceClient,
  isGrpcError,
  extractGoogleAdsApiError,
} from 'google-ads-api-client';


/**
 * the transport enables making authenticated api calls
 */
const transport = getAuthenticatedGoogleAdsApiGrpcTransport({
  clientId: '__CLIENT_ID__',
  clientSecret: '__CLIENT_SECRET__',
  refreshToken: '__REFRESH_TOKEN__',
  developerToken: '__DEVELOPER_TOKEN__',
});

/**
 * each service that google has in the google ads api has its own code-generated client
 *
 * note:
 * - you'll notice their online documentation is grouped per service
 * - your IDE will show you all of the available methods google exposes on each service through this client
 * - this client uses the authenticated transport you created above
 *
 * ref:
 * - https://developers.google.com/google-ads/api/reference/rpc/v11/overview#services
 */
const client = new CustomerServiceClient(transport);

/**
 * you can use the clients to make any request google supports
 *
 * note:
 * - wrap the request in a try-catch to decode errors the grcp api might throw (otherwise, they'll be unreadable)
 * - they come with jsdocs, so hover over the methods in your IDE to get more details
 * - each method is well documented online, so you can easily google-search the method to get google's official docs
 * - everything has type defs, so you can be sure you're making valid requests 🙂
 */
try {
  const { status, response } = await client.listAccessibleCustomers({});
  expect(status.code).toEqual('OK');
  expect(response.resourceNames.length).toBeGreaterThan(0);
} catch (error: any) {
  if (isGrpcError(error)) throw extractGoogleAdsApiError(error);
  throw error;
}

lookup geo target constant locations by name

ref:

  • https://developers.google.com/google-ads/api/docs/targeting/location-targeting
  const client = new GeoTargetConstantServiceClient(transport);
  try {
    const { response, status } = await client.suggestGeoTargetConstants(
      SuggestGeoTargetConstantsRequest.create({
        // https://developers.google.com/google-ads/api/reference/rpc/v11/SuggestGeoTargetConstantsRequest
        countryCode: 'US',
        query: {
          oneofKind: 'locationNames',
          locationNames: { names },
        },
      }),
    );
    expect(status.code).toEqual('OK');
    expect(response.geoTargetConstantSuggestions.length).toBeGreaterThan(0);
  } catch (error: any) {
    if (isGrpcError(error)) throw extractGoogleAdsApiError(error);
    throw error;
  }

generate keyword ideas

per google

Using the KeywordPlanIdeaService, you can search for new keywords that are relevant to your Google Search campaign, or find historical metrics on keywords.

ref:

  • https://developers.google.com/google-ads/api/docs/keyword-planning/generate-keyword-ideas
  const client = new KeywordPlanIdeaServiceClient(transport);
  try {
    const { response, status } = await client.generateKeywordIdeas(
      GenerateKeywordIdeasRequest.create({
        // https://developers.google.com/google-ads/api/reference/rpc/v11/GenerateKeywordIdeasRequest
        customerId: config.google.ads.account.manager.customerId,
        geoTargetConstants: locationResourceNames,
        includeAdultKeywords: false,
        pageToken: undefined as any, // google's proto typedef doesn't match comments here
        pageSize: page.size,
        keywordPlanNetwork:
          KeywordPlanNetworkEnum_KeywordPlanNetwork.GOOGLE_SEARCH,
        keywordAnnotation: [
          KeywordPlanKeywordAnnotationEnum_KeywordPlanKeywordAnnotation.KEYWORD_CONCEPT,
        ],
        seed: {
          oneofKind: 'keywordSeed',
          keywordSeed: { keywords: [seed] },
        },
      }),
    );
    expect(status.code).toEqual('OK');
    expect(response.results.length).toBeGreaterThan(0);
  } catch (error: any) {
    if (isGrpcError(error)) throw extractGoogleAdsApiError(error);
    throw error;
  }

development

  1. install the protoc binary from google
PROTOC_ZIP=protoc-3.20.3-linux-x86_64.zip
curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.20.3/$PROTOC_ZIP
sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
sudo unzip -o $PROTOC_ZIP -d /usr/local 'include/*'
rm -f $PROTOC_ZIP
protoc --version
# libprotoc 3.20.3
  1. download the protos from google and generate typedefs and serde from them
./src/protos/sync.sh # takes ~20min, so be patient

api access

Google has a delightfully complicated process for getting access to their api 😄

In order to get access, you'll need to:

  • get a developerToken: https://developers.google.com/google-ads/api/docs/first-call/dev-token
  • get an OAuth clientId and clientSecret: https://developers.google.com/google-ads/api/docs/oauth/cloud-project
  • get a refreshToken from the user you want to impersonate: https://developers.google.com/google-ads/api/docs/client-libs/python/oauth-web
  • create a test account: https://developers.google.com/google-ads/api/docs/first-call/test-accounts

context

protobuf, rpc, grpc

google uses two google-built technologies, protobuf and rpc, to maximize their api performance.

  • protobuf is a way of serializing and deserializing data
    • alternatives:
      • json
      • xml
    • differences:
      • protobuf uses a schema when serializing + deserializing to achieve maximum performance + type saftey
        • these schemas are typically defined in a .proto file
      • protobuf schemas can be used to generate type definitions in any language
        • e.g., https://github.com/stephenh/ts-proto
    • similarities:
      • each language has to implement their own encoding + decoding utility
      • it serializes data in a deserlizable way
    • refs:
      • https://stackoverflow.com/questions/52409579/protocol-buffer-vs-json-when-to-choose-one-over-another
  • rpc is a pattern for sending data over http (i.e., over internet)
    • alternatives
      • rest
      • graphql
    • differences
      • endpoint naming convention; https://stackoverflow.com/a/44240048/3068233
        • rpc: http://MyRestaurant:8080/Orders/PlaceOrder (POST: {Tacos object})
        • rest: http://MyRestaurant:8080/Orders/Order?OrderNumber=asdf (POST: {Tacos object})
    • similarities
      • uses http infrastructure to communicate (GET, POST)
      • sends serialized data over http
    • refs:
      • https://stackoverflow.com/questions/26830431/web-service-differences-between-rest-and-rpc
      • https://cloud.google.com/blog/products/api-management/understanding-grpc-openapi-and-rest-and-when-to-use-them

when used together, protobuf + rpc = grpc

protos

proto = protobuf schema

google publicly exposes their protos here: https://github.com/googleapis/googleapis/tree/master/google/ads/googleads

for example:

// https://github.com/googleapis/googleapis/blob/master/google/ads/googleads/v11/resources/ad.proto
// An ad.
message Ad {
  option (google.api.resource) = {
    type: "googleads.googleapis.com/Ad"
    pattern: "customers/{customer_id}/ads/{ad_id}"
  };

  // Immutable. The resource name of the ad.
  // Ad resource names have the form:
  //
  // `customers/{customer_id}/ads/{ad_id}`
  string resource_name = 37 [
    (google.api.field_behavior) = IMMUTABLE,
    (google.api.resource_reference) = {
      type: "googleads.googleapis.com/Ad"
    }
  ];

  // Output only. The ID of the ad.
  optional int64 id = 40 [(google.api.field_behavior) = OUTPUT_ONLY];

  // The list of possible final URLs after all cross-domain redirects for the
  // ad.
  repeated string final_urls = 41;

  // A list of final app URLs that will be used on mobile if the user has the
  // specific app installed.
  repeated google.ads.googleads.v11.common.FinalAppUrl final_app_urls = 35;

  // The list of possible final mobile URLs after all cross-domain redirects
  // for the ad.
  repeated string final_mobile_urls = 42;

  //...

we use these schemas to generate typescript typedefs and serde (serialize-deserialize) methods with this tool: https://github.com/timostamm/protobuf-ts/

for example:


/**
 * An ad.
 *
 * @generated from protobuf message google.ads.googleads.v11.resources.Ad
 */
export interface Ad {
    /**
     * Immutable. The resource name of the ad.
     * Ad resource names have the form:
     *
     * `customers/{customer_id}/ads/{ad_id}`
     *
     * @generated from protobuf field: string resource_name = 37;
     */
    resourceName: string;
    /**
     * Output only. The ID of the ad.
     *
     * @generated from protobuf field: int64 id = 40;
     */
    id: bigint;
    /**
     * The list of possible final URLs after all cross-domain redirects for the
     * ad.
     *
     * @generated from protobuf field: repeated string final_urls = 41;
     */
    finalUrls: string[];
    /**
     * A list of final app URLs that will be used on mobile if the user has the
     * specific app installed.
     *
     * @generated from protobuf field: repeated google.ads.googleads.v11.common.FinalAppUrl final_app_urls = 35;
     */
    finalAppUrls: FinalAppUrl[];
    /**
     * The list of possible final mobile URLs after all cross-domain redirects
     * for the ad.
     *
     * @generated from protobuf field: repeated string final_mobile_urls = 42;
     */
    finalMobileUrls: string[];

    // ...