Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

breaking: upgrade to google ads api v6.1 #201

Merged
merged 37 commits into from
Mar 2, 2021
Merged

breaking: upgrade to google ads api v6.1 #201

merged 37 commits into from
Mar 2, 2021

Conversation

kritzware
Copy link
Contributor

@kritzware kritzware commented Feb 9, 2021

change log in progress

Warning! Breaking changes, use at your own risk. Beta release available on ^v4.0.4-beta.0, which will be upped to v5.0.0 after we run some internal tests.

@kritzware kritzware added enhancement 🎉 google ads release 🚀 New releases of the library next release 🚀 Will be included in the next release of the library labels Feb 9, 2021
kritzware and others added 7 commits February 10, 2021 10:42
* mutation hooks

* comments

* tests and type reorganisation

* updated hooks in readme

* readme edits
…erpart (#203)

* numeric enum contraint values converted to string counterparts

* tests

* remove debug

* remove debug
@avermeil avermeil mentioned this pull request Mar 2, 2021
@kritzware kritzware merged commit 6759a35 into master Mar 2, 2021
@kritzware
Copy link
Contributor Author

BREAKING

The library now uses Google Bazel build files to generate TypeScript proto services & definitions, previously being compiled manually by us. This means all internal code of the library (google-ads-node) has changed. As this required a complete rewrite of the library, there are a number of breaking changes:

  • CIDs specified in client.Customer must no longer include dashes. This format is no longer supported 123-456-7890 , instead pass in 1234567890

  • The types export has been removed, and replaced with several other exports to match the official documentation. The following are now available from google-ads-api: enums , resources, common, errors and services. Resources can now also be class based (more on this further down). Here's how defining a Campaign and Ad would change:

    // -- OLD --
    import { enums, types } from "google-ads-api"
    
    const campaign: types.Campaign = {
    	name: "Planet Express",
    	status: enums.CampaignStatus.ENABLED,
    }
    const ad: types.Ad = { ... }
    
    // -- NEW --
    import { enums, resources, common } from "google-ads-api"
    
    /* campaign type inferred, or use "campaign: resources.Campaign" */
    const campaign = new resources.Campaign({
    	name: "Planet Express",
    	status: enums.CampaignStatus.ENABLED,
    })
    const ad = new common.Ad({ ... })

    Note: you don't have to use these classes if instead you prefer to use standard objects. You will still benefit from type assertions and autocomplete.

  • All entities such as Campaigns, Ads, Keywords, etc. now directly come from the compiled protos, and therefore are now (optionally) class based. They should be created with new . All entities include a built-in helper method toJSON.

    const campaign = new resources.Campaign({ ... })
    campaign.name = "Planet Express"
    
    console.log(campaign, campaign.toJSON())
    
    await customer.campaigns.create([campaign])
    
    // You can also use plain objects, the following works:
    await customer.campaigns.create([
    	{
    		name: "Planet Express",
    	}
    ])
  • Service methods e.g. campaign.create used to optionally take a single resource or an array of resources. They now only support the array style.

    // This won't work anymore
    await customer.campaigns.create(campaign)
    
    // Instead always use an array argument, even for single resources
    await customer.campaigns.create([campaign])
  • The service method list has been removed. Instead you should specify the exact fields you need using the customer.report method. The get method still exists, but should still not be used in production. You can find more info for the reasons why here.

  • The delete service method has been renamed to remove to match the official documentation.

  • Hooks have been updated (there were previously undocumented). There are now separate hooks for queries and mutations that can be executed before, after and upon an error of an operation. Query hooks have access to the GAQL query and report options, and mutation hooks have access to the mutation operations.

    • onQueryStart - executed before a query/report/reportStream. Has access to the cancel() method which will cancel the query if called. If an argument is provided to cancel() then this will be returned from the query instead. Otherwise the return value will be undefined. Also has access to the editOptions() method that takes a partial copy of new requestOptions such as as validate_only. Each key in these partial request options will overwrite the original request options key while preserving those that remain.
    • onQueryError - executed if a query/report/reportStream throws an error. Has access to the error body with the error argument.
    • onQueryEnd - executed after a query/report/reportStream. Has access to the results of the query with the response argument. Also has access to the resolve() method that will cause the query to return an alternative value to the response.
    • onMutationStart - executed before mutateResources. Has access to the cancel() method which will cancel the mutation if called. If an argument is provided to cancel() then this will be returned from the mutation instead. Otherwise the return value will be undefined.
    • onMutationError - executed if mutateResources throws an error. Has access to the error body with the error argument.
    • onMutationEnd - executed after mutateResources. Has access to the response of the mutation with the response argument. Also has access to the resolve() method that will cause the mutation to return an alternative value to the response. Also has access to the editOptions() method that takes a partial copy of new mutateOptions such as as validate_only. Each key in these partial request options will overwrite the original request options key while preserving those that remain.
    const customer = new Customer({
    	clientOptions,
    	customerOptions,
    	hooks: {
        // Query hooks
    		onQueryStart({ credentials, query, reportOptions, cancel, editOptions }) {
    			if (reportOptions.entity === "campaign") {
    			  cancel("alternative result");
          }
          if (reportOptions.entity === "ad_group") {
            editOptions({ validate_only: true });
          }
    		},
    		onQueryError({ credentials, query, reportOptions, error }) {
    			console.log(error);
    		},
    		onQueryEnd({ credentials, query, reportOptions, response, resolve }) {
    			resolve(response.slice(0, 5));
    		},
        // Mutation hooks
    		onMutationStart({ credentials, method, mutation, cancel, editOptions }) {
    			cancel("alternative result");
    		},
    		onMutationError({ credentials, method, mutation, error }) {
    			console.log(error);
    		},
    		onMutationEnd({ credentials, method, mutation, response, resolve }) {
    			if (reponse.partial_failure_error) {
            resolve({});
          }
    		},
    	}
    })

New/Added

  • Upgraded to v6.1 of the Google Ads API. See the official change notes here.

  • Support for all services and their corresponding methods as specified in the official Google Ads API documentation.

  • The default return type (i.e. when not using generics) for a report is now IGoogleAdsRow rather than any. However we recommend building custom types to pass as generics, e.g.

    type Campaign = Pick<resources.Campaign, 'resource_name' | 'name' | 'status'>
    
    const campaigns = await customer.report<Campaign[]>({
    	entity: "campaign",
    	attributes: ["campaign.resource_name", "campaign.name", "campaign.status"]
    })
  • A reportStream method to stream the results of larger queries. It returns an async iterable that should be iterated over with an asynchronous for ... of loop.

    const stream = customer.reportStream({
    	entity: "campaign",
    	attributes: ["campaign.name"]
    });
    
    for await (const row of stream) {
      ...
    }
  • When an operation would cause multiple errors, only one error would be reported at a time due to the way the protocol buffer response was decoded. The error interface now fully matches the docs, being decoded correctly with an array of errors. This means all operation errors are now returned up front, rather than one at a time.

  • A ResourceNames module with functions to build any resource name, and a corresponding string literal type.

    import { ResourceNames } from "google-ads-api"
    const customer_id = 12345
    const campaign_id = 67890
    const rn: ResourceNames.CampaignResourceName =
    	ResourceNames.campaign(customer_id, campaign_id)
    	// "customers/12345/campaigns/67890"
  • A sort_order key in the report options.

    const result = await customer.report({
    	entity: "campaign",
    	attributes: ["campaign.name"],
    	sort_by: "metrics.clicks",
    	sort_order: "DESC",
    })

Fixed

  • Many existing bugs have been automatically resolved by using the more robustly generated TypeScript protos.

Removed

  • Usage of the grpc dependency. The recommend library to use now is @grpc/grpc-js. Thanks to @xpirt for originally bringing this up in #37.
  • Bottleneck library. This was used internally with Redis to limit the number of requests sent per second, to avoid hitting rate limits. This should instead be handled in your own implementation of the library, if required.

@eliotik
Copy link
Contributor

eliotik commented Mar 15, 2021

Hi @kritzware in this release logging was removed, any reasons why? How one can add a hook to analyze requests and responses sent/received to/from API?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
google ads release 🚀 New releases of the library next release 🚀 Will be included in the next release of the library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants