Installing Instant AI for Headless Shopify Sites

Instant has native integrations into Shopify, however Shopify Headless stores require a custom integration, with five steps:

  1. Connecting to the Shopify API
  2. Installing Instant's Identification Pixel
  3. Tracking Customer Events
  4. Updating Event Properties

Please contact your customer success manager if you experience any issues. We are happy to guide you or your developers through this implementation if needed.


Step 1: Connecting to Shopify's API

The first step of the integration process requires connecting to Shopify's API.

  1. Proceed to the Instant dashboard and go to Pixel > Select Shopify. You will see the instructions for connecting to Shopify's API under "Step 1: Shopify API Setup".
  2. Follow these instructions and verify your integration.

Step 2: Installing Instant's Identification Pixel

The first step of the integration process requires adding Instant's pixel to your site. This allows Instant to identify anonymous shoppers who visit your website.

  1. Proceed to the Instant dashboard and go to Pixel > Select Shopify. You will see instructions to complete your pixel setup under Step 2: Storefront Pixel.
  2. Follow these instructions and verify your integration.

Step 3: Tracking Customer Events

Event triggers determine when Instant interaction events are sent and contain all the relevant information to generate a relevant email. Throughout your website, where you may be sending events to an alternative email provider, you will also need to send them to Instant.

  1. Add track calls for the following events, if you are able to track them.
    • PAGE_VIEWED
    • COLLECTION_VIEWED
    • PRODUCT_VIEWED
    • ITEM_ADDED_TO_CART
    • CART_VIEWED
    • CHECKOUT_STARTED
  2. Update all existing usages of window.InstantJS.track() to add new calls to track events and send to provider INSTANT. If you are using another provider, such as Klaviyo, your events may look like the below. If not, you may have just Instant listed.

For Example: If multiple providers

window.InstantJS?.track("ITEM_ADDED_TO_CART", [
{
provider: "KLAVIYO",
event: {
// ...
},
},
{
provider: "INSTANT",
event: {
// ...
},
},
]);

For Example: If just Instant

window.InstantJS?.track("ITEM_ADDED_TO_CART", [
{
provider: "INSTANT",
event: {
// ...
},
},
]);
  1. The instant event object supports three top level properties
  • For ITEM_ADDED_TO_CART, use both cart and items:
  • cart.items must include all items currently in the cart
  • top-level items field should include only the new item(s) being added
type InstantEvent = {
provider: "INSTANT";
event: {
/** Current state of the cart */
cart?: InteractionCart;
/** Items that were added or removed from the cart */
items?: InteractionCartItem[];
/** The product or products that were interacted with */
products?: InteractionProduct[];
};
};
  1. You can provide as many of these properties as are available, but certain events need specific top-level properties.
    • PAGE_VIEWED
      • products
    • COLLECTION_VIEWED
      • products
    • PRODUCT_VIEWED
      • products
    • ITEM_ADDED_TO_CART
      • cart
      • items
    • CART_VIEWED
      • cart
    • CHECKOUT_STARTED
      • cart
  2. Note that you can provide more than just the properties list here per event, e.g. if you always have access to the cart object, then you are free to include it on all events, but it is not required.

Examples

Replace the URL examples below with your own that’s relevant to the URL structure of your cart or store checkout.

  • ITEM_ADDED_TO_CART
window.InstantJS?.track("ITEM_ADDED_TO_CART", [
{
provider: "KLAVIYO",
event: {
CheckoutURL: "",
Items: [
{
ProductName: "",
Quantity: "1",
ItemPrice: "19.95",
ImageURL: "",
},
{
ProductName: "",
Quantity: "1",
ItemPrice: "221.95",
ImageURL: "",
},
],
},
},
{
provider: "INSTANT",
event: {
cart: {
cart_url: "<https://store.store.com/cart/c/Z2NwLWFzaWEtc291dGhlYXN0MTowMUpZNjFIWTBTMUhTTlNLTVEzMUE2UUVUNw?key=b5be5fb92dc9c590a8e9d2efbf678eeb>",
currency: "AUD",
grand_total: 20000,
cart_id: "",
discounts: [],
sub_total: 20000,
shipping_total: 0,
tax_total: 0,
transaction_id: "",
items: [
{
item_id: "12345",
item_name: "Example Product",
item_sku: "EX-PROD-001",
product_id: "prod_12345",
product_sku: "prod_sku_12345",
product_name: "Example Product Name",
product_description: "This is an example product description.",
product_brand: "Example Brand",
product_type: "Example Type",
variant_id: "var_12345",
variant_sku: "var_sku_12345",
variant_title: "Example Variant Title",
quantity: 1,
price: 20000,
currency: "AUD",
handle: "example-product-handle",
affiliation: "",
categories: [],
options: [],
image: {
url: "<https://example.com/image.jpg>",
},
online_store_url: "<https://yourstore.com/range/range>", },
],
},
items: [
{
item_id: "12345",
item_name: "Example Product",
item_sku: "EX-PROD-001",
product_id: "prod_12345",
product_sku: "prod_sku_12345",
product_name: "Example Product Name",
product_description: "This is an example product description.",
product_brand: "Example Brand",
product_type: "Example Type",
variant_id: "var_12345",
variant_sku: "var_sku_12345",
variant_title: "Example Variant Title",
quantity: 1,
price: 20000,
currency: "AUD",
handle: "example-product-handle",
affiliation: "",
categories: [],
options: [],
image: {
url: "<https://example.com/image.jpg>",
},
online_store_url: "<https://yourstore.com/range/range>",
            },
],
},
},

]);

  • PRODUCT_VIEWED
window.InstantJS?.track("PRODUCT_VIEWED", [
{
provider: "KLAVIYO",
event: {
Items: [
{
ProductName: "Example Product Name",
Quantity: "1",
ItemPrice: "19.95",
ImageURL: "<https://example.com/image.jpg>",
},
],
},
},
{
provider: "INSTANT",
event: {
products: [
{
product_id: "prod_12345",
product_sku: "prod_sku_12345",
product_name: "Example Product Name",
product_description: "This is an example product description.",
product_brand: "Example Brand",
product_type: "Example Type",
variant_id: "var_12345",
variant_sku: "var_sku_12345",
variant_title: "Example Variant Title",
price: 20000,
currency: "AUD",
handle: "example-product-handle",
affiliation: "",
categories: [],
options: [],
image: {
url: "<https://example.com/image.jpg>",
},
online_store_url: "<https://yourstore.com/range/range>", },
],
},
},
]);

Types for track function

/******************** TYPES ********************/

type InteractionProductOption = {
/** The label of the option, e.g. "Color" */
label: string;
/** The value of the option, e.g. "Red" */
value: string;
/** The ID of the option, e.g. "OPTION-1" */
option_id: string;
/** The value of the option, e.g. "OPTION-1-VALUE-1" */
option_value: string;
};

type InteractionProductImage = {
url: string;
aspect_ratio?: number;
alt?: string;
height?: number;
width?: number;
};

type InteractionProductCollection = {
id: string;
name: string;
};

type InteractionProduct = {
/** The ID of the product, e.g. "prod_12345" */
product_id: string;
/** The SKU of the product, e.g. "BLANKET-SMALL" */
product_sku: string;
/** The name of the product, e.g. "Blanket" */
product_name: string;
/** The description of the product. e.g. "A fluffy blanket" */
product_description?: string;
/** The brand of the product. e.g. "Google" */
product_brand?: string;
/** The type of the product. e.g. "custom", "gift_card" */
product_type?: string;

/** The ID of the product variant */
variant_id?: string;
/** The SKU of the product variant */
variant_sku?: string;
/** The title of the variant SKU. e.g. "Small" */
variant_title?: string;

/** The price of the product, in the smallest unit of the currency */
price?: number | null;
currency?: string;

/** Collections that this product belongs under. */
categories?: InteractionProductCollection[];
/** The affiliate of the product. e.g. "Google" */
affiliation?: string;
/** Available options that the product has. */
options?: InteractionProductOption[];

/** The URL of the product image */
image: InteractionProductImage;
/** The handle of the product. e.g. "blanket-small" */
handle?: string;
/** The url of the product page */
online_store_url?: string;
};

type InteractionCartItem = InteractionProduct & {
/** The ID of the cart item */
item_id: string;
quantity: number;
item_name?: string;
item_sku?: string;
};

type InteractionPurchaseDiscount = {
id: string;
type: "DISCOUNT_CODE";
percentage: number;
amount: number;
};

type InteractionCart = {
/** The URL of the cart page */
cart_url: string;
cart_id?: string | null;
currency?: string | null;
transaction_id?: string | null;
/** The total amount of the cart after shipping and discounts in the smallest unit of the currency */
tax_total?: number | null;
/** The total amount of the cart before shipping and discounts in the smallest unit of the currency */
sub_total?: number | null;
/** The total amount of shipping costs in the smallest unit of the currency */
shipping_total?: number | null;
/** The total amount of the cart in the smallest unit of the currency */
grand_total?: number | null;
discounts?: InteractionPurchaseDiscount[];
/** All items currently in the cart */
items: InteractionCartItem[];
};

type KlaviyoEvent = {
provider: "KLAVIYO";
event: unknown;
};

type InstantEvent = {
provider: "INSTANT";
event: {
/** Current state of the cart */
cart?: InteractionCart;
/** Items that were added or removed from the cart */
items?: InteractionCartItem[];
/** The product or products that were interacted with */
products?: InteractionProduct[];
};
};

type InteractionType =
| "PAGE_VIEWED"
| "COLLECTION_VIEWED"
| "PRODUCT_VIEWED"
| "ITEM_ADDED_TO_CART"
| "CART_VIEWED"
| "CHECKOUT_STARTED";

/******************** GLOBALS ********************/

export {};
declare global {
interface Window {
InstantJS?: {
track: (type: InteractionType, body: (KlaviyoEvent | InstantEvent)[]) => void;
};
}
}

Testing your Implementation

Open DevTools Console and verify InstantJS.track() is firing with the correct provider payloads and confirm:

  • cart_url is complete
  • online_store_url exists for each product
  • All cart items are present in cart.items
  • Newly added items are only in items