google-ads-api Node.js Client Library

repository·master·Indexed 43 days ago

https://github.com/opteo/google-ads-api

An unofficial, high-performance Node.js client library for the Google Ads API (version 25.1.0). It provides full TypeScript support for Google Ads resources, enums, and services using REST and Protocol Buffers. Features include GAQL query support via query() and report(), memory-efficient async iterators for large datasets via reportStream() and queryStream(), atomic mutations with mutateResources(), and a flexible hooks system to intercept requests and errors.

Tokens
22.3K
Snippets
60
Records
66
Agent score
72%

What's inside google-ads-api

  1. Use hooks to intercept queries, streams, mutations, and services

    master

    Hooks allow you to execute logic before, after, or on error for various operations.

    Pre-request hooks (executed before)

    • onQueryStart: For query and report.
    • onStreamStart: For reportStream and reportStreamRaw.
    • onMutationStart: For mutations.
    • onServiceStart: For services.

    Capabilities:

    • cancel(alternativeValue): Cancels the action. The alternativeValue becomes the return value of the operation.
    • editOptions(options): Modifies request options (e.g., setting validate_only: true).

    Error hooks (executed on error)

    • onQueryError: For query and report.
    • onStreamError: For reportStream (not reportStreamRaw).
    • onMutationError: For mutations.
    • onServiceError: For services.

    Post-request hooks (executed after)

    • onQueryEnd: For query and report.
    • onMutationEnd: For mutations.
    • onServiceEnd: For services.

    Note: There is no onStreamEnd hook to avoid blocking the thread or accumulating stream results.

    import { OnQueryStart, OnQueryError, OnQueryEnd } from "google-ads-api";
    
    // Example: Pre-request hook
    const onQueryStart: OnQueryStart = async ({ cancel, editOptions }) => {
      if (env.mode === "test") {
        cancel([]); // Cancels and returns [] as the result
      }
      if (env.mode === "dev") {
        editOptions({ validate_only: true });
      }
    };
    
    // Example: Error hook
    const onQueryError: OnQueryError = async ({ error }) => {
      console.log(error.message);
    };
    
    // Example: Post-request hook
    const onQueryEnd: OnQueryEnd = async ({ response, resolve }) => {
      const [first] = response;
      resolve([first]);
    };
    
    const customer = client.Customer(
      { clientOptions, customerOptions },
      { onQueryStart, onQueryError, onQueryEnd }
    );
  2. Include a summary row in reports

    master

    When using the report method, you can request a summary row by setting return_summary_row: true in search_settings. The summary row will be returned as the first element in the results array.

    When using the reportStream method, the summary row will be the final iterated row in the stream.

    // Using report method (summary is first)
    const [summaryRow, ...response] = await customer.report({
      entity: "campaign",
      metrics: ["metrics.clicks", "metrics.all_conversions"],
      search_settings: {
        return_summary_row: true,
      },
    });
    
    // Using reportStream method (summary is last)
    const stream = customer.reportStream({
      entity: "campaign",
      metrics: ["metrics.clicks", "metrics.all_conversions"],
      search_settings: {
        return_summary_row: true,
      },
    });
    
    const accumulator = [];
    for await (const row of stream) {
      accumulator.push(row);
    }
    const summaryRow = accumulator.slice(-1)[0];
  3. Handle Google Ads errors with GoogleAdsFailure

    master

    Most errors (except GRPC connection/timeout issues) are instances of GoogleAdsFailure. You can catch these and inspect the errors array to find specific GoogleAdsError instances and their error codes.

    import { errors } from "google-ads-api";
    
    try {
      await customer.query(`SELECT campaign.bad_field FROM campaign`);
    } catch (err) {
      if (err instanceof errors.GoogleAdsFailure) {
        console.log(err.errors); // Array of GoogleAdsError instances
    
        const [firstError] = err.errors;
        if (
          firstError.error_code.query_error ===
          errors.QueryErrorEnum.QueryError.UNRECOGNIZED_FIELD
        ) {
          console.log(`Error: using invalid field "${firstError.trigger}" in query`);
        }
      }
    }
  4. Install google-ads-api via npm

    master

    Install the library using npm. This project requires Node.js 22 or newer. It supports both ES modules (import) and CommonJS (require).

    Note: You can also import enums and field types directly from google-ads-api/enums and google-ads-api/fields without loading the full gRPC service clients.

    npm install google-ads-api
  5. Define report constraints and filters

    master

    Constraints allow you to filter report results. You can provide constraints in several formats:

    1. Simple String: A raw GAQL-style constraint string.
    2. ConstraintType1 (Key-Op-Value): An object specifying a key, an operator, and a value.
    3. ConstraintType2 (Key-Value mapping): An object mapping keys directly to values (implies equality).
    4. Array of Constraints: An array containing any of the above.

    Supported Operators (ConstraintOperation): = , !=, >, >=, <, <=, IN, NOT IN, LIKE, NOT LIKE, CONTAINS ANY, CONTAINS ALL, CONTAINS NONE, IS NULL, IS NOT NULL, DURING, BETWEEN, REGEXP_MATCH, NOT REGEXP_MATCH.

    ConstraintKey: Can be any fields.Attribute, fields.Metric, or fields.Segment.

    // Example of ConstraintType1
    const constraints: Constraints = [
      {
        key: fields.Attribute.CampaignStatus,
        op: '=',
        val: 'ENABLED'
      },
      {
        key: fields.Metric.Clicks,
        op: '>',
        val: 10
      }
    ];
    
    // Example of ConstraintType2
    const simpleConstraints: Constraints = {
      [fields.Attribute.CampaignName]: 'Summer_Sale'
    };
  6. Handle Google Ads partial failure errors

    master

    The Google Ads API can return partial failures, where some operations in a request succeed while others fail. The library provides a mechanism to decode these errors.

    When a response contains a partial_failure_error, the library can decode the details buffer into a structured errors.GoogleAdsFailure object. This allows you to inspect exactly which operations failed within a batch request.

  7. Use Hooks to intercept Google Ads API requests

    master

    The Hooks interface allows you to intercept and modify the lifecycle of queries, streams, mutations, and service calls. You can use these hooks to log activity, modify request options, cancel operations, or provide alternative responses.

    Available Hook Categories

    1. Query Hooks (query and report methods)

    Used for standard GAQL queries.

    • onQueryStart: Called before execution. Provides cancel and editOptions.
    • onQueryError: Called when a query throws an error.
    • onQueryEnd: Called after successful execution. Provides response and resolve.

    2. Stream Hooks (reportStream and reportStreamRaw methods)

    Used for streaming report data.

    • onStreamStart: Called before the stream begins. Provides cancel and editOptions.
    • onStreamError: Called when the stream throws an error (Note: This is not called for errors in reportStreamRaw).

    3. Mutation Hooks (mutateResources or service-specific mutations)

    Used for operations that change data.

    • onMutationStart: Called before execution. Provides cancel and editOptions.
    • onMutationError: Called when a mutation fails.
    • onMutationEnd: Called after successful execution. Provides response and resolve.

    4. Service Hooks (Direct service calls like customer.campaigns.create)

    Used for individual service method calls.

    • onServiceStart: Called before the service method executes. Provides cancel and editOptions.
    • onServiceError: Called when a service method fails.
    • onServiceEnd: Called after successful execution. Provides response and resolve.

    Common Hook Utilities

    When using Start hooks, you are provided with two critical utility functions:

    • cancel(args?): Cancels the operation. If you pass an argument to cancel, the original method call will return that argument instead of the actual API response.
    • editOptions(options): A function to modify the request or mutation options (e.g., RequestOptions or MutateOptions) before the request is sent.
  8. Build type-safe Google Ads resource names

    master

    The ResourceNames module provides type-safe builders for constructing Google Ads resource name strings. These strings are required for identifying specific entities (like campaigns, ad groups, or customers) in API requests. Each builder function accepts string | number arguments and returns a template literal type that ensures the resulting string follows the exact format required by the Google Ads API.

    Common patterns include:

    • Simple resources: customer(id), campaign(customerId, campaignId)
    • Hierarchical resources: campaignAsset(customerId, campaignId, assetId, fieldType)
    • Complex/View resources: campaignSimulation(customerId, campaignId, type, modificationMethod, startDate, endDate)
    // Example: Creating a Campaign resource name
    const campaignName = ResourceNames.campaign(1234567890, 987654321);
    // Result: "customers/1234567890/campaigns/987654321"
    
    // Example: Creating a CampaignAsset resource name
    const assetName = ResourceNames.campaignAsset(1234567890, 987654321, 11223344, 55667788);
    // Result: "customers/1234567890/campaignAssets/987654321~11223344~55667788"
  9. Retrieve Campaigns with metrics using report()

    master

    Use the report method to fetch entities along with their metrics. You specify the entity, attributes, metrics, and optional constraints (filters) and limit.

    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",
        "metrics.impressions",
        "metrics.all_conversions",
      ],
      constraints: {
        "campaign.status": enums.CampaignStatus.ENABLED,
      },
      limit: 20,
    });
  10. Create an expanded text ad

    master

    To create an expanded text ad, define a resources.Ad object with the expanded_text_ad details and the appropriate type. Then, create a resources.AdGroupAd to link the ad to an ad group and use customer.adGroupAds.create() to perform the mutation.

    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]);
  11. Retrieve Ad Group metrics by date

    master

    Fetch metrics for an ad_group entity segmented by date. You must provide from_date and to_date when using segments like segments.date.

    import { enums } from "google-ads-api";
    
    const campaigns = await customer.report({
      entity: "ad_group",
      metrics: [
        "metrics.cost_micros",
        "metrics.clicks",
        "metrics.impressions",
        "metrics.all_conversions",
      ],
      segments: ["segments.date"],
      from_date: "2021-01-01",
      to_date: "2021-02-01",
    });
  12. Handle raw streams with reportStreamRaw()

    master

    For manual control over stream events, use reportStreamRaw(). This returns a raw stream where rows are delivered in chunks (e.g., 10,000 rows). You can use the parse function from google-ads-api to convert these chunks into usable results.

    import { enums, parse } from "google-ads-api";
    
    const reportOptions = {
      entity: "ad_group_criterion",
      attributes: [
        "ad_group_criterion.keyword.text", 
        "ad_group_criterion.status",
      ],
      constraints: {
        "ad_group_criterion.type": enums.CriterionType.KEYWORD,
      },
    };
    
    const stream = customer.reportStreamRaw(reportOptions);
    
    // Rows are streamed in 10,000 row chunks
    stream.on("data", (chunk) => {
      const parsedResults = parse({
        results: chunk.results,
        reportOptions,
      });
    });
    
    stream.on("error", (error) => {
      throw new Error(error);
    });
    
    stream.on("end", () => {
      console.log("stream has finished");
    });