Pixel tracking on the post-purchase page

If your store has installed an app that adds a post-purchase page to your store's checkout, then any custom pixel tracking that you use on your store might not capture certain tracking events. Custom tracking pixels that are added to your store's Additional scripts box track events on only the order status page, which comes after the post-purchase page in the checkout. If a customer leaves your store on the post-purchase page, then no events on the order status page are tracked.

To ensure that you capture conversion events properly, you can add a script that tracks events on the post-purchase page. This script can also track additional purchases that are made from the post-purchase page, such as upsells. After you add a post-purchase page script, you need to adjust your order status page script to ignore events that are already captured by the post-purchase page script.

You need to change how your store tracks events only if you use a custom tracking pixel. For example, if you set up Google Analytics through Online Store > Preferences, then it already captures events correctly on your post-purchase page.

Considerations

The post-purchase page additional script is similar to the order status page additional scripts, but with a few key differences:

  • The script is added to the post-purchase page, not the order status page.
  • The field allows only JavaScript. Liquid code isn't accepted.
  • The only HTML tag allowed is <script>.
  • The script runs within a sandbox and isn't included on the main page.
  • You can add a post-purchase page script only if your store has installed an app that adds a post-purchase page to your checkout.

Running the script within a sandbox ensures that the script is secure and is used for its intended purpose.

Shopify Support can’t help with post-purchase page scripts. If you need assistance, then you can post in the Shopify Community or hire a Shopify Expert.

Compatibility with scripts on the order status page

To ensure that your pixels correctly track all conversion events, set up tracking scripts on both the post-purchase page and the order status page. To avoid counting conversion events twice, you can use the post_purchase_page_accessed Liquid variable in scripts that run on the order status page.

If a customer lands on the post-purchase page and then navigates to the order status page, then the post_purchase_page_accessed variable returns true. If a customer doesn't arrive at the post-purchase page, then the variable returns false.

For example, you can use the following format for your scripts on the order status page:

{% if first_time_accessed == true and post_purchase_page_accessed == false %}
<script>
   // insert your tracking script
</script>
{% endif %}

Available APIs

You can use JavaScript globals to give tracking scripts access to the data that they need. The accessible data is available under window.Shopify.

Tracking purchases made on the post-purchase page

To track additional purchases that are made through the post-purchase page, you can subscribe to the Shopify.on event.

After you subscribe, the following actions occur whenever a post-purchase changeset is successfully applied:

  • Your handler is called with two Order-type arguments: order and outdated order.
  • The globals under window.Shopify are updated so that the scripts can use the updated data.

Handlers subscribed to this event can have as little as 500 ms to execute. Make sure to load any dependencies that you need ahead of time.

Add the post-purchase page script

  1. From your Shopify admin, go to Settings > Checkout.
  2. In the Post-purchase additional scripts field, enter your script.
  3. Click Save.

Example script

You can use the following basic script template to help you build your own post-purchase page script. This example script uses Google Analytics to track the initial conversion, and explains how to track additional purchases. This example is very simple and your final script will likely differ from it.

Example script files

Example script for the order status page:

<script async src="https://www.googletagmanager.com/gtag/js?id=G-FYNQ742HTX"></script>
<script>
(function() {
  // make sure the initial conversion isn't tracked twice
  {% if first_time_accessed == false or post_purchase_page_accessed == true %}
    return;
  {% endif %}
  // set up google analytics
  window.dataLayer = window.dataLayer || [];
  function gtag() {
    dataLayer.push(arguments);
  }
  gtag('js', new Date());
  gtag('config', 'G-FYNQ742HTX');
  // track initial conversion
  var order = window.Shopify.order;

  gtag('event', 'purchase', {
    affiliation: 'My Shopify Store',
    transaction_id: Number(order.id).toString(),
    value: order.totalPrice,
    currency: order.currency,
    items: order.lineItems.map((item) => ({
      id: Number(item.id).toString(),
      name: item.title,
      category: item.product.type,
      price: item.price,
      quantity: item.quantity,
      variant: Number(item.variant.sku).toString(),
    })),
  });
})();
</script>

Example script for the post-purchase page:

<script async src="https://www.googletagmanager.com/gtag/js?id=G-FYNQ742HTX"></script>
<script>
(function() {
  // set up google analytics
  window.dataLayer = window.dataLayer || [];

  function gtag() {
    dataLayer.push(arguments);
  }

  gtag('js', new Date());
  gtag('config', 'G-FYNQ742HTX');

  // make sure the initial conversion isn't tracked twice
  if (!Shopify.wasPostPurchasePageSeen) {
    var order = window.Shopify.order;

    // track initial conversion
    gtag('event', 'purchase', {
      affiliation: 'My Shopify Store',
      transaction_id: Number(order.id).toString(),
      value: order.totalPrice,
      currency: order.currency,
      items: order.lineItems.map(function(item) {
        return {
          id: Number(item.id).toString(),
          name: item.title,
          category: item.product.type,
          price: item.price,
          quantity: item.quantity,
          variant: Number(item.variant.sku).toString(),
        };
      }),
    });
  }

  // set up additional conversion tracking
  Shopify.on('CheckoutAmended', function(newOrder, previousOrder) {
    // identify which items were recently added, if any
    var oldItems = previousOrder.lineItems.map(function (line) { return line.id; });

    var addedItems = newOrder.lineItems.filter(
      function (line) { return oldItems.indexOf(line.id) < 0; }
    );

    // no new items were added, so we skip conversion tracking
    if (addedItems.length === 0) {
      return;
    }

    // track additional purchase
    gtag('event', 'purchase', {
      affiliation: 'My Shopify Store',
      transaction_id: Number(order.id).toString(),
      value: order.totalPrice,
      currency: order.currency,
      items: addedItems.map(function (item) {
        return {
          id: Number(item.id).toString(),
          name: item.title,
          category: item.product.type,
          price: item.price,
          quantity: item.quantity,
          variant: Number(item.variant.sku).toString(),
        };
      }),
    });
  });
})();
</script>

References

The following table contains the type definitions for the attributes that are exposed to post-purchase additional scripts through window.Shopify:

Field Definition
window.Shopify
shop The details of the shop from where the order was placed.
order The details of the order.
pageUrl The current page's URL.
wasPostPurchasePageSeen Whether the customer viewed the post-purchase page during this checkout. It will be false when rendering for the first time, and true otherwise, such as if the page is reloaded.
on(event: string, handler: function): void Subscribes to an event. Currently, only the CheckoutAmended event is supported.
off(event: string, handler: function): void Unsubscribes handler from the given event. Currently, only the CheckoutAmended event is supported.
Shop
id The ID of the shop.
currency The store's currency in ISO 4217 format. For example, USD. For more details, refer to shop.currency.
Order
id The order's internal identifier.
number The integer representation of the order name. For example, 1025.
checkoutToken The checkout's internal identifier.
customer The customer associated with the order.
lineItem The line items for the order.
subtotalPrice The subtotal price of all the items in the order after both line-item and cart discounts have been applied. The subtotal doesn't include taxes (unless taxes are included in the prices), shipping costs, or tips.
totalPrice The total price of the order.
currency The ISO 4217 code of the order's currency.
discounts The sum of the amount of the discounts applied to the order.
Customer
id The ID of the customer.
email The email address of the customer.
acceptsMarketing Whether the customer had accepted marketing. It will be true if the customer accepts marketing, and false if not.
hasAccount Whether the customer email is associated with a customer account. It will be true if the email is listed on a customer account, and false if not. For more details, refer to customer.has_account.
firstName The first name of the customer.
lastName The last name of the customer.
ordersCount The total number of orders that the customer has placed.
totalSpent The total amount that the customer has spent on all orders.
LineItem
finalLinePrice The combined price of all the items in the line item. This is equal to line_item.final_price multiplied by line_item.quantity.
finalPrice The price of the line item, including all line-level discount amounts.
lineLevelTotalDiscount The total amount of all discounts applied to the line item specifically. This doesn't include discounts that are added to the cart.
optionsWithValues An array of selected values from the item's product options. For more details, refer to line_item.options_with_values.
originalLinePrice The combined price of the quantity of items included in the line, before discounts were applied. This is equal to line_item.original_price multiplied by line_item.quantity.
originalPrice The original price of the line item before discounts were applied.
price The unit price of the line item. The price reflects any discounts that are applied to the line item. Available only to stores located in Germany or France.
product The product of the line item.
properties An array of custom information for an item that has been added to the cart. For more information, refer to line_item.properties.
quantity The quantity of the line item.
title The title of the line item. For more information, refer to line_item.title.
variant The variant of the line item.
Product
id The ID of the product.
type The type of the product.
ProductVariant
id The ID of the variant.
sku The SKU of the variant.
CartDiscount
id The discount application's internal identifier.
code The code of the discount, if it has one.
type The type of the discount. Possible values are: automatic, discount_code, manual, and script.
amount The total amount that the price of the order is reduced by the discount.

Ready to start selling with Shopify?

Try it free