Monday, August 19, 2024

Shopify Function Extension Example

This blog builds upon my previous blog, Shopify Check UI Extension Example. Now that we got our Checkout Extensibility app running, it's time to add another payment method. Why do we need to add another payment method? Surely, that's commen sense is the answer to that, right? Having more payment options will let your store cater to more potential customers.

One popular payment method is Paypal. To activate Paypal, on the Shopify admin page, we go the Settings > Payments > Activate Paypal and then follow the instructions. The payment setup would look like below.

Fantastic. Now that we have activated Paypal, we should see something like below on checkout.

Paypal Express Checkout Problem

Well and good that we can accept Paypal payments. But the issue now is that some customers are abandoning the checkout step because they don't have Paypal and it is right at the top of the page. It is making them believe that it is the only payment option. It is confusing the customers especially on mobile view because it's the first thing they see as it is positioned at the top. Our simple requirement now is keep the Paypal payment method and at the same time remove or hide the Paypal express checkout button. Sounds easy enough?

Shopify Function Solution

As mentioned earlier, we are building the Shopify Function extension from my previous blog, Shopify Check UI Extension Example. I'm assuming you have the GitHub repository for it. If not, you can pull from github.com/jpllosa/checkout-practice-app. First off the bat is to generate the extension like so. I've named the extension hide-paypal-express and coding it in JavaScript.

  
C:\shopify\checkout-practice-app>npm run generate extension

> checkout-practice-app@1.0.0 generate
> shopify app generate extension


To run this command, log in to Shopify.
👉 Press any key to open the login page on your browser
✔ Logged in.
╭─ info ─────────────────────────────────────────────────────────────────────────╮
│                                                                                │
│  Using shopify.app.toml:                                                       │
│                                                                                │
│    • Org:             Joel Patrick Llosa                                       │
│    • App:             checkout-practice-app                                    │
│                                                                                │
│   You can pass `--reset` to your command to reset your app configuration.      │
│                                                                                │
╰────────────────────────────────────────────────────────────────────────────────╯

?  Type of extension?
√  Payment customization - Function

?  Name your extension:
√  hide-paypal-express

?  What would you like to work in?
√  JavaScript


╭─ success ──────────────────────────────────────────────────────────────────────╮
│                                                                                │
│  Your extension was created in extensions/hide-paypal-express.                 │
│                                                                                │
╰────────────────────────────────────────────────────────────────────────────────╯

  

Update Scopes

Our scopes on the shopify.app.toml should have been updated with the read_payment_customizations and write_payment_customizations. If not, add them like below and do a deploy to push the scopes to the Partner dashboard.

  
# shopify.app.toml
...snipped...
[access_scopes]
# Learn more at https://shopify.dev/docs/apps/tools/cli/configuration#access_scopes
scopes = "read_payment_customizations,write_payment_customizations"
...snipped...
  
  
C:\shopify\checkout-practice-app>npm run deploy

> checkout-practice-app@1.0.0 deploy
> shopify app deploy

╭─ info ─────────────────────────────────────────────────────────────────────────╮
│                                                                                │
│  Using shopify.app.toml:                                                       │
│                                                                                │
│    • Org:             Joel Patrick Llosa                                       │
│    • App:             checkout-practice-app                                    │
│    • Include config:  Yes                                                      │
│                                                                                │
│   You can pass `--reset` to your command to reset your app configuration.      │
│                                                                                │
╰────────────────────────────────────────────────────────────────────────────────╯

?  Release a new version of checkout-practice-app?
√  Yes, release this new version


Releasing a new app version as part of checkout-practice-app

free-shirt-1000     │ Bundling UI extension free-shirt-1000...
hide-paypal-express │ Building function hide-paypal-express...
hide-paypal-express │ Building GraphQL types...
free-shirt-1000     │ free-shirt-1000 successfully built
hide-paypal-express │ Bundling JS function...
hide-paypal-express │ Running javy...
hide-paypal-express │ Done!


╭─ success ──────────────────────────────────────────────────────────────────────╮
│                                                                                │
│  New version released to users.                                                │
│                                                                                │
│  checkout-practice-app-2 [1]                                                   │
│                                                                                │
╰────────────────────────────────────────────────────────────────────────────────╯
[1] https://partners.shopify.com/31716511/apps/1338089799691/versions/3168605962251
  

Enable the Shopify Function

Next step is to grab the function ID to enable the Shopify function and create the payment customization. For this I've installed GraphiQL app to make executing queries and mutations against my store easier. You can find the function ID the Partners page like below.

Run the paymentCustomizationCreate mutation via the GraphiQL app to enable your Shopify function. Don't forget to replace the function ID. You should have a response like below after that.

  
mutation {
  paymentCustomizationCreate(paymentCustomization: {
    functionId: "<replace with function ID>"
    title: "checkout practice app"
    enabled: true
  }) {
    paymentCustomization {
      id
    }
    userErrors {
      message
    }
  }
}
  

Response

  
{
  "data": {
    "paymentCustomizationCreate": {
      "paymentCustomization": {
        "id": "gid://shopify/PaymentCustomization/283772501"
      },
      "userErrors": []
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 10,
      "actualQueryCost": 10,
      "throttleStatus": {
        "maximumAvailable": 2000,
        "currentlyAvailable": 1990,
        "restoreRate": 100
      }
    }
  }
}
  

Just provide your shop domain to install the GraphiQL App.

To check what payment customizations have been enabled on your store, run the paymentCustomizations query like below.

  
query {
  paymentCustomizations(first: 100) {
    edges {
      node {
        id
        title
      }
    }
  }
}
  

Response

  
{
  "data": {
    "paymentCustomizations": {
      "edges": [
        {
          "node": {
            "id": "gid://shopify/PaymentCustomization/283772501",
            "title": "checkout practice app"
          }
        }
      ]
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 11,
      "actualQueryCost": 3,
      "throttleStatus": {
        "maximumAvailable": 2000,
        "currentlyAvailable": 1997,
        "restoreRate": 100
      }
    }
  }
}
  

Hide Paypal Express Checkout

Before we hide the Paypal Express Checkout button, let's see how it looks without any logic added to the scaffolding code. Run npm run dev. Go to the checkout page, the top of the page will show the Paypal Express checkout and the bottom will have the standard Paypal payment method. Next, go to your Partners dashboard then your app extensions runs. You should see the logs on what goes in, out and errors. It's empty for now because we haven't added a query and applied any logic to the result of the query.

Under extensions/hide-paypal-express, edit the run.graphql with the query below. This will fetch a list of payment methods available on our checkout.

  
query RunInput {
  paymentMethods {
    id
    name
  }
}
  

On the same directory, edit run.js as below. What this code does is fairly simple. Probably does not need any explanation as it is fairly readable and understandable. We just check for a Paypal Express Checkout payment menthod and if it exists apply the hide operation to it by providing the payment method ID and placement. Express checkout is AcceleratedCheckout. Otherwise, return with no changes to the payment methods.

  
// @ts-check

import { PaymentCustomizationPaymentMethodPlacement } from "../generated/api";

/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

/**
 * @type {FunctionRunResult}
 */
const NO_CHANGES = {
  operations: [],
};

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const hidePaymentMethod = input.paymentMethods.find(
    (method) =>
      method.name.toLocaleLowerCase().trim() === "paypal express checkout"
  )

  if (hidePaymentMethod) {
    return {
        operations: [
        {
          hide: {
            paymentMethodId: hidePaymentMethod.id,
            placements: [PaymentCustomizationPaymentMethodPlacement.AcceleratedCheckout]
          }
        }
      ]
    }
  }

  return NO_CHANGES;
};
  

Save your changes and the changes should hot reload. If not, do npm run dev again. Go to the checkout page and the Paypal Express Checkout button should be gone now.

Debugging a Shopify Function

To debug a shopify function, go to your Partners dashboard then your app extensions runs as described above. This time you should see some logs because we have added a query in run.graphql and we have returned an operation. You should have something like below. If you want to dump some values of variables for example, calls to console.error are shown under Logs (STDERR).

Input (STDIN)

  
{
  "paymentMethods": [
    {
      "id": "gid://shopify/PaymentCustomizationPaymentMethod/0",
      "name": "(for testing) Bogus Gateway"
    },
    {
      "id": "gid://shopify/PaymentCustomizationPaymentMethod/1",
      "name": "Deferred"
    },
    {
      "id": "gid://shopify/PaymentCustomizationPaymentMethod/2",
      "name": "PayPal Express Checkout"
    }
  ]
}
  

Output (STDOUT)

  
{
  "operations": [
    {
      "hide": {
        "paymentMethodId": "gid://shopify/PaymentCustomizationPaymentMethod/2",
        "placements": [
          "ACCELERATED_CHECKOUT"
        ]
      }
    }
  ]
}
  

Shopify Function Closing

There you have it. A handy way to hide the Paypal Express Checkout option in Shopify Checkout. As usual, entire code is available at github.com/jpllosa/checkout-practice-app. Thank you for reading.