HomeGuidesAPI Reference
ChangelogHelp CenterCommunityContact Us

Integrate with a Shopify Hydrogen store

Learn how to integrate with a Shopify Hydrogen store, or with any headless Shopify store using a custom storefront

While this guide uses examples for Shopify's Hydrogen framework, the concepts and principles are true for any setup where you are using Shopify to power your ecommerce store’s backend, but have a custom storefront (a “headless” setup). This integration requires 2 main steps:

  1. Connect your Shopify store via Klaviyo’s native integration to sync order, catalog, and subscriber data
  2. Manually add code snippets to your site to enable onsite tracking functionality

📘

For free accounts

As discussed below, if you don't have redirect rules in place from the myshopify.com domain to your hosted domain, or don't want shoppers to see the myshopify.com domain in Klaviyo emails, you will need to contact Klaviyo's customer support team to update the product URLs that automatically sync through your catalog. If you are using Klaviyo's free plan, you have 60 days of dedicated email support after account creation during which you can submit a request. After the 60 day period, you must upgrade your account to submit further requests.

Key integration components

The key components of integrating this type of ecommerce solution are:

  • Customer data
    Tracking information such as name, email, phone number, and other profile attributes
  • Subscribers
    Tracking who opts in and to what marketing channel (e.g., your email newsletter subscribers)
  • Order activity
    Tracking when a customer places an order, what products are ordered, etc.
  • Products
    The items in your catalog
  • Website activity
    Tracking who is active on your site, what products they view, etc.

With the exception of website activity, Klaviyo’s native Shopify integration will sync all of the above data for a headless Shopify store because this data is fetched server-side via API. 

Additionally, if you don't have redirect rules in place from the myshopify.com domain to your hosted domain, or don't want shoppers to see the myshopify.com domain in Klaviyo emails, you will need to request that Klaviyo support update the product URLs that automatically sync through your catalog. Read the catalog section below to learn more. 

Connect Klaviyo’s native Shopify integration

The first step is to integrate your Shopify store via Klaviyo’s native integration. Follow the steps in our Getting started with Shopify guide through step 14. Ignore the Onsite Tracking box and its status; you’ll add onsite tracking manually later.

Enable onsite tracking

For headless setups, you will need to manually install Klaviyo's “Active on Site” JavaScript (also known as Klaviyo.js). Klaviyo.js tracks when users are active on your site and enables Klaviyo forms.

If you want to track when users view specific products on your site (which can be leveraged in a browse abandonment flow), you’ll need to add Klaviyo’s Viewed Product tracking JavaScript snippet. Below, we provide code snippets and guidance for tracking Active on Site, Viewed Product, and Added to Cart events, which allow you to send cart abandonment flows.

📘

Based on your Customer Privacy settings in Shopify, Klaviyo may not track onsite events (including Active on Site, Viewed Product, and Added to Cart) for visitors to your Shopify store in the EU, EEA, UK and Switzerland, unless they have provided consent. This does not affect logged-in user tracking.

Add Active on Site tracking

With Hydrogen 2, you’ll want to include import {Script} from '@shopify/hydrogen'; in root.jsx and add our standard onsite snippet within a Script element. Replace the placeholder value for the company_id in the example below with your Klaviyo Public API key.

export default function App() {
  const nonce = useNonce();
  /** @type {LoaderReturnData} */
  const data = useLoaderData();

  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width,initial-scale=1" />
        <Meta />
        <Links />
      </head>
      <body>
        <Layout {...data}>
          <Outlet />
        </Layout>
        <Script async type="text/javascript"
  src="//static.klaviyo.com/onsite/js/klaviyo.js?company_id=YourPublicKey" />
        <ScrollRestoration nonce={nonce} />
        <Scripts nonce={nonce} />
      </body>
    </html>
  );
}

Add Viewed Product and Added to Cart tracking

To implement Viewed Product and Added to Cart tracking, we recommend first creating a component for our onsite tracking. In the example below, we create an Onsite component in app/components/Onsite.jsx and then add our standard Viewed Product and Added to Cart tracking requests.

Make sure to update the values of the JSON properties in the snippet so that they dynamically pull from the relevant information needed for that property.

export function trackViewedProduct(product) {
    let klaviyo = window.klaviyo || [];
    let item = {
        Name: product.title,
        ProductID: product.id.substring(product.id.lastIndexOf('/') + 1),
        ImageURL: product.selectedVariant.image.url,
        Handle: product.handle,
        Brand: product.vendor,
        Price: product.selectedVariant.price.amount,
        Metadata: {
          Brand: product.vendor,
          Price: product.selectedVariant.unitPrice,
          CompareAtPrice: product.selectedVariant.compareAtPrice,
        }
};
klaviyo.push(['track', 'Hydrogen Viewed Product', item]);
klaviyo.push(['trackViewedItem', item]);


}

export function trackAddedToCart(product) {
let klaviyo = window.klaviyo || []
let item = {
        Name: product.title,
        ProductID: product.id.substring(product.id.lastIndexOf('/') + 1),
        ImageURL: product.selectedVariant.image.url,
        Handle: product.handle,
        Brand: product.vendor,
        Price: product.selectedVariant.price.amount
      }
      klaviyo.push(['track', 'Hydrogen Added To Cart', item])
}

You can now import those functions into your product file (for example, app/routes/products.$handle.jsx). Import the onsite functions and useEffect into your product file:

import { useEffect } from "react";
import {trackViewedProduct, trackAddedToCart} from '~/components/Onsite';

Then, you can load trackViewedProduct on page load via useEffect within your Product() function. Here’s an example of how this would look within your products.$handle.jsx file:

export default function Product() {
  /** @type {LoaderReturnData} */
  const {product, variants} = useLoaderData();
  const {selectedVariant} = product;

  // Execute VP on page load ***

  useEffect(() => {
    trackViewedProduct(product);
  },[]);


  return ( ...

For trackAddedToCart, you’ll want to invoke this within your added to cart click handler. Here’s an example snippet using the ProductForm() function:

function ProductForm({product, selectedVariant, variants}) {

  // define atc ***
  const handleAtc = function () {
    trackAddedToCart(product)
  }

  return (
    <div className="product-form">
      <VariantSelector
        handle={product.handle}
        options={product.options}
        variants={variants}
      >
        {({option}) => <ProductOptions key={option.name} option={option} />}
      </VariantSelector>
      <br />
      <AddToCartButton
        disabled={!selectedVariant || !selectedVariant.availableForSale}
        onClick={() => {
          // Add our newly created click handler ***
          handleAtc();
          window.location.href = window.location.href + '#cart-aside';
        }}
        lines={
          selectedVariant
            ? [
                {
                  merchandiseId: selectedVariant.id,
                  quantity: 1,
                },
              ]
            : []
        }
      >
        {selectedVariant?.availableForSale ? 'Add to cart' : 'Sold out'}
      </AddToCartButton>
    </div>
  );
}

With our onsite scripts, forms should appear on local environments without any issues. However, content security policies can impact the functionality of our scripts both on local and production environments. We suggest testing through preview builds sent up to Shopify via Oxygen or custom deployments. If you encounter issues, you’ll need to configure your CSP to allow our JavaScript to function.

Example code for onsite tracking

Klaviyo has provided reference code to showcase how to implement the onsite tracking above. You can also check out the test store that utilizes this reference code.

Update your Shopify catalog URLs

Your Shopify catalog will sync with Klaviyo through the native integration, though the product catalog in Klaviyo will autopopulate with the myshopify.com URL. Contact Klaviyo support to request an update to this setting.

The URL can be updated from:
https://[INSTANCE].myshopify.com/products/[PRODUCT_HANDLE]
to:
https://[STOREFRONT_URL]/products/[PRODUCT_HANDLE]

Server-side and onsite metrics

Once you connect your store, the following metrics will sync through Klaviyo’s native Shopify integration:

  • Checkout Started
    When customers start a checkout and provide their contact information
  • Placed Order
    When an order successfully processes on your system
  • Ordered Product
    An event for each item in a processed order
  • Fulfilled Order
    When an order is sent to the customer
  • Fulfilled Partial Order
    When an order that has been placed is partially fulfilled
  • Canceled Order
    When an order is canceled
  • Refunded Order
    When a customer’s order is refunded

📘

Checkout Started events will sync only if customers enter contact and shipping information on the first page of the checkout process and click continue.

For more information about metrics synced from Shopify and their properties, check out our Shopify data reference

The following onsite metrics can be tracked in Klaviyo by manually adding code snippets to your site:

  • Active on Site
    When someone visits your website
  • Viewed Product
    When someone views a product 
  • Recently Viewed Items
    Recently viewed items for a specific profile
  • Added to Cart
    When someone adds an item to their cart
  • Logged in user tracking
    Identify and track the activity of logged in users

Additional resources

Klaviyo resources

Shopify resources