Google Pay API gives users the opportunity to pay everywhere, using the payment information stored in their Google Accounts. In this lab, you make use of Google Pay's client library for Web to improve the checkout experience of a simplified sample online store, by creating a faster, more convenient and safer experience, which in turn leads to more conversions and happier customers.

Auto T-Shirt Shop is an innovative store that leverages the latest advances in artificial intelligence and using information like style preferences, weather, time of the year and fashion trends, suggests you the most appropriate item to purchase.

Metrics on engagement are over the roof. Unfortunately, numbers also reflect a large number of abandonments during the checkout process. Determined to tackle that, one of the owners of the project recalls having seen a video showing the promising results that Google Pay yielded for other similar sites, so they decide to give it a go and trust you to take care of the integration.

What you will build

This codelab walks you through integrating Google Pay into an existing site, including determining whether a user is able to pay using a payment method supported by Google Pay, the placement and design of the payment button and the execution of the transaction.

What you'll learn

What you will need

Run the sample site in

In order to get up and running as quickly as possible, this codelab has been made available in Glitch is a free web based environment that features a number of tools such as a code editor or hosting and deployment functionality, that allow you to build and serve web applications.

To get started, use the button below to provision a new development environment on Glitch already set up with a copy of this codelab.

Start development environment on

From here on, you can use the code editor on Glitch to modify your files, and once you are ready, start serving your application using the "Show Live" button.

Skim through the sample site

As you can see, the repository features an uncomplicated file structure. The primary objective of this codelab is to give you the ability to adapt this integration to your existing and future applications, independently of the framework, libraries or tools you choose to work with.

Explore the site

The web application that this codelab builds on is a demo marketplace that, using a very advanced machine learning model, suggests one t-shirt to the visitor based on a number of very complex features. Now, if you happen to ask yourself why does the site recommends you a different t-shirt every time you reload the site; well..., truth be told, the very advanced machine learning model is just a random generator (sorry).

This demo marketplace has been built in a way that it humbly resembles how your existing or potential application might look like today, before you add a means of purchase. In fact, even though we recommend you to work on top of this demo application, you are free to go ahead and use this codelab to integrate Google Pay into your existing applications.

Now, if you have not already done so, open the demo site as it currently stands. To do that, click on the "Show" button if you are using Glitch or open the URL where your local web server is running.

If you were able to see the demo site: nothing surprising, right? A product detail page, with a picture, the price, a description, some selectors and a button to take you to an imaginary and ordinary payment form.

The objective of this lab is to replace this, in principle, tedious flow with a two-click experience powered by Google Pay.

Let's plan this!

To better understand this integration, the process is broken apart into the following fundamental steps:

  1. Load the library
  2. Determine ability to pay with Google Pay
  3. Show the button to pay with Google Pay
  4. Create and send the request for payment
  5. Collect the results

Add the script tag

The first thing you need to do in order to start using the Google Pay API is load the JavaScript library. To do that, include a script tag in the HTML file from where you are intending to call the API, including a src attribute that points to the external JS library. For this codelab, this file is index.html:

<script async

As you can see, in addition to src, you have added two other attributes.

Instantiate the API client

Once your script has loaded, everything is set for you to start using this library. Start by instantiating the client object, which you will use to make calls to the Google Pay API later on. You can do that inside of the index.js file, which is already part of the file structure in this project.

let googlePayClient;
function onGooglePayLoaded() {
  googlePayClient = new google.payments.api.PaymentsClient({
    environment: 'TEST'

The payment client is initialized with a PaymentOptions object. Setting the environment to TEST allows you to experiment with dummy payment information across the entire integration. Once you are ready to create operations that support real transactions, you can update the environment property to PRODUCTION.

The skeleton

Every time you communicate with the Google Pay API, there are a number of configuration parameters that you need to include in your requests, such as the version of the API you are targeting. For the purpose of this codelab, this object also contains information about the payment methods accepted in your application. The final structure looks as follows:

  apiVersion: number,
  apiVersionMinor: number,
  allowedPaymentMethods: Array

The property allowedPaymentMethods takes a list of payment methods. For every payment method you are required to include the following properties:

  type: 'CARD',
  parameters: {
    allowedCardNetworks: Array.<string>,
    allowedAuthMethods: Array.<string>

In addition to type and parameters, you later add the tokenizationSpecification property, which is not necessary to determine whether the user in question is able to pay with Google Pay, but it is used by the PaymentDataRequest call to define how the data related to the payment method selected is to be handled. But let's take one step at a time.

The payment method configuration

In this example, you are only going to accept card payments for Mastercard and Visa, both in a tokenized and primary account number (PAN) forms. This is how your payment method looks like:

const baseCardPaymentMethod = {
  type: 'CARD',
  parameters: {
    allowedCardNetworks: ['VISA','MASTERCARD'],
    allowedAuthMethods: ['PAN_ONLY','CRYPTOGRAM_3DS']

Putting it all together

Let's recap.

You have defined one payment method to be accepted in your website, and you are going to work with version 2.0 of the API. This is how the resulting configuration should look like:

const baseCardPaymentMethod = {
  type: 'CARD',
  parameters: {
    allowedCardNetworks: ['VISA','MASTERCARD'],
    allowedAuthMethods: ['PAN_ONLY','CRYPTOGRAM_3DS']

const googlePayBaseConfiguration = {
  apiVersion: 2,
  apiVersionMinor: 0,
  allowedPaymentMethods: [baseCardPaymentMethod]

Now that you have your base configuration ready, let's get to the fun part.

One of the main objectives of Google Pay is to provide a faster and more convenient checkout experience to your users. This not only applies to situations in which your users are able to leverage Google Pay to do that, but also in those where they don't. Using the isReadyToPay request allows you to determine readiness to pay with Google Pay, and an opportunity for you to modify the experience in your site accordingly.

Is your user able to pay with Google Pay?

The first thing that you want to do is check whether a specific user who is about to pay in your site, is able to use Google Pay to do so. This request requires you to specify the version of the Google Pay API and allowed payment methods in your site. This is exactly what the base configuration object defined in the previous step contains:

  .then(function(response) {
    if(response.result) {
      // Add Google Pay button – createAndAddButton()
    } else {
      // Unable to pay using Google Pay
  }).catch(function(err) {
    console.error("Error determining readiness to use Google Pay: ", err);

As you can see, if the call fails or returns with an unsuccessful response, there is no further action to be taken in the context of Google Pay. In this situation, the most appropriate next step would be to show additional UI that supports other means of payment.

On the other hand, if the response is successful, you are now ready to allow your users to benefit from using Google Pay, and thus, you can go ahead and add a button to initiate the payment process on user activation (eg.: button click).

Add a button to pay with Google Pay

Even though you can use any button that follows Google Pay's brand guidelines to start the payment process, it is recommended to generate one using the Google Pay API. This way, you not only ensure an accurate use of the aforementioned brand guidelines, but you also benefit from other improvements built directly into the button, such as localization.

To do that, you use the createButton method in the PaymentsClient object, including ButtonOptions to configure the button:

function createAndAddButton() {

  const button = googlePayClient.createButton({

    // currently defaults to black if default or omitted
    buttonColor: 'default',

    // defaults to long if omitted
    buttonType: 'long',

    onClick: onGooglePaymentsButtonClicked


function onGooglePaymentsButtonClicked() {
  // TODO: Perform transaction

The only required property when using createButton is onClick, which is necessary to determine the callback object or function to trigger every time your users activate the button. buttonColor and buttonType allow you to customize how your button looks like. Tweak them accordingly based on the theme and UI requirements of your application.

Once the button is created, all you need to do is add it to an appropriate node within the DOM. In this example, a div node identified with buy-now is used for this purpose.

See that you also defined a function to handle button click events. In the next section, you use this function to request a payment method.

Prepare the payment request

At this point, you have loaded the Google Pay API and determined that the user in your site is able to use Google Pay to make a payment. As a result, you have shown the Google Pay payment button in the UI and now your user is ready to initiate the transaction. It is now time to load the final payments sheet containing the forms of payment available for the different logged in users.

Just like you did before during the definition of the isReadyToPay request, this call also requires the properties in the base configuration object defined earlier (apiVersion, apiVersionMinor and allowedPaymentMethods) in addition to some new ones. This time, there is a new property called tokenizationSpecification, and additional parameters in your payment methods that are relevant for the purpose of this request. In addition, transactionInfo and merchantInfo need to be added as well.

Include additional required information in your payment methods

Start by creating a copy of the base card payment method used before. This card payment method now requires a tokenizationSpecification property to define how to handle the data related to the payment method selected, as well as further data requirements needed for the actual transaction: in this example, a full billing address and phone number are required.

The tokenizationSpecification property

The tokenization specification determines how the payment method selected by your customers is handled and used to complete a transaction.

There are two different types of handling strategies supported. If you are processing the payment transaction from within your PCI DSS compliant servers, use the DIRECT specification type. In this example, you use a payment gateway to process the payment, hence, you set the PAYMENT_GATEWAY specification type. This is how your tokenization specification shall look like:

const tokenizationSpecification = {
  parameters: {
    gateway: 'example',
    gatewayMerchantId: 'gatewayMerchantId'

In the parameters section, you can specify a gateway from the list of providers supported by the Google Pay API, along with additional configuration required by each gateway. For the purpose of this lab, it is sufficient to use the example gateway, which yields test results for the transactions executed.

Additional parameters

Similarly, you can now provide more details about the information that you need to request in order to successfully place the transaction. See how in this example, you need to add the properties billingAddressRequired and billingAddressParameters, to indicate that for this transaction the billing address of the user is required in full format and including a phone number.

const cardPaymentMethod = {
  type: 'CARD',
  tokenizationSpecification: tokenizationSpecification,
  parameters: {
    allowedCardNetworks: ['VISA','MASTERCARD'],
    allowedAuthMethods: ['PAN_ONLY','CRYPTOGRAM_3DS'],
    billingAddressRequired: true,
    billingAddressParameters: {
      format: 'FULL',
      phoneNumberRequired: true

Adding information about the transaction

The transactionInfo property contains an object with financial details about the transaction, namely the price and currency code (ISO 4217 alpha format) along with the status of the price, which can be either final or estimated depending on the nature of the transaction (eg.: the price may vary depending on the shipping address specified):

const transactionInfo = {
  totalPriceStatus: 'FINAL',
  totalPrice: '123.45',
  currencyCode: 'USD'

Adding information about the merchant

The payment request takes information about the merchant performing the request under the merchantInfo property. In this codelab you will focus on two of them:

Once ready, simply add the information about the merchant to the paymentDataRequest object:

const merchantInfo = {
  merchantId: '01234567890123456789',
  merchantName: 'Example Merchant Name'

Request payment information and process the result

Now, merge the previously defined configuration into the final object and pass it on to the loadPaymentData request :

const paymentDataRequest = Object.assign({}, googlePayBaseConfiguration, {
  allowedPaymentMethods: [cardPaymentMethod],
  transactionInfo: transactionInfo,
  merchantInfo: merchantInfo   

At this point, you have everything you need to ask the Google Pay API for a valid form of payment. To do that, use the loadPaymentData method in the PaymentsClient object, passing in the configuration that you just defined:

  .then(function(paymentData) {
    // Process result – processPaymentData(paymentData);
  }).catch(function(err) {
    // Log error: { statusCode: CANCELED || DEVELOPER_ERROR }

Calling this method triggers the presentation of the Google Pay payment sheet. If there are no configuration errors, you can see a list of valid payment methods associated with the currently logged in account.

Upon selection, the sheet closes and the Promise is fulfilled with a PaymentData object including relevant information about the payment method selected:

  "apiVersionMinor": 0,
  "apiVersion": 2,
  "paymentMethodData": {
    "description": "Visa •••• 1234",
    "tokenizationData": {
      "type": "PAYMENT_GATEWAY",
      "token": "examplePaymentMethodToken"
    "type": "CARD",
    "info": {
      "cardNetwork": "VISA",
      "cardDetails": "1234",
      "billingAddress": {
        "phoneNumber": ...,

You can now use this payment method information to perform the actual transaction.

function performPayment(paymentData) {
  const paymentMethodToken = paymentData.paymentMethodData.tokenizationData.token;
  // Sample TODO: Use this token to perform a payment through your payment gateway

So far we've looked at transactions with fixed payment amounts, but suppose you wanted to update the price based on the selection of certain properties of the transaction (eg.: the shipping details). You can achieve this by supplying the paymentDataCallback parameter when constructing the client. This callback is used for you to handle changes on the transaction and to apply modifications accordingly. You can listen to changes on the shipping address, shipping option and payment method selected. In this example, you are going to listen for changes to the shipping option selected. First up, define the variables containing all of the shipping information, and modify paymentDataRequest to include them:

const shippingOptionParameters = {
  shippingOptions: [
      id: 'shipping-001',
      label: '$1.99: Standard shipping',
      description: 'Delivered on May 15.'
      id: 'shipping-002',
      label: '$3.99: Expedited shipping',
      description: 'Delivered on May 12.'
      id: 'shipping-003',
      label: '$10: Express shipping',
      description: 'Delivered tomorrow.'

// Shipping surcharges mapped to the IDs above.
const shippingSurcharge = {
  'shipping-001': 1.99,
  'shipping-002': 3.99,
  'shipping-003': 10

paymentDataRequest.shippingAddressRequired = true;
paymentDataRequest.shippingOptionRequired = true;
paymentDataRequest.callbackIntents = ['SHIPPING_OPTION'];
paymentDataRequest.shippingOptionParameters =  shippingOptionParameters;

Next, you modify the creation of the googlePayClient to include a paymentDataCallback, which is called whenever a modification included in the callbackIntents is made to the payment operation. This callback includes an object with the properties changed. You can use these changes to construct an updated payment transaction:

function onGooglePayLoaded() {
  googlePayClient = new google.payments.api.PaymentsClient({
    paymentDataCallback: paymentDataCallback,
    environment: 'TEST'

function paymentDataCallback(callbackPayload) {

  const selectedShippingOptionId =;
  const shippingSurcharge = shippingSurcharge[selectedShippingOptionId];
  const priceWithSurcharges = 123.45 + shippingSurcharge;

  return {
    newTransactionInfo: {
      totalPriceStatus: 'FINAL',
      totalPrice: priceWithSurcharges.toFixed(2),
      totalPriceLabel: 'Total',
      currencyCode: 'USD',
      displayItems: [
          label: 'Subtotal',
          type: 'SUBTOTAL',
          price: priceWithSurcharges.toFixed(2),
          label: 'Shipping',
          type: 'LINE_ITEM',
          price: shippingSurcharge.toFixed(2),
          status: 'FINAL'

Upon return of this new object in the callback, the information presented in the payment sheet is updated to reflect the modifications made to the transaction.

Now that you have tested that the integration works adequately, you can go one step further and prefetch your payment configuration as soon as you have determined that Google Pay can be used, while the user deliberates about whether to activate the Google Pay payment button. This way, by the time your user decides to pay, the information that the sheet needs in order to load will already be available, significantly reducing the load time, and therefore improving the overall experience.

This method expects the same input as loadPaymentData. That is, you can use the same paymentDataRequest object defined before. Now, all you need to do is include a call to the prefetch method as soon as you have determined that the user can use Google Pay, that is, right after isReadyToPay returns successfully:

  .then(function(response) {
    if(response.result) {

Just like that, you have impacted the responsiveness of your site and the overall user experience, which altogether are great ingredients for improving the ratio of conversions.

You have successfully integrated Google Pay API into the sample site in this codelab or your own application.

Now, to take this into production do not forget to take a look at the integration checklist. Once completed and reviewed, you will receive a merchant identifier to add to your client configuration. Similarly, if you are planning to use (or already using) a third party payment processor or gateway, check out the list of supported providers on Google Pay and configure yours. If you are integrating with Google Pay directly, take a look at the documentation section on this topic.

What we've covered

Next steps

Learn more

Did you find this useful?

Very useful! Just enough to meet expectations. Not really.

Would you like to see other codelabs to help you with other types of integration (Android, direct integration, loyalty APIs) ?

Yes please, that'd be grand! I'm happy with what I got.