1. Visually Help Center
  2. Headless Integrations

Visually.io | Generic Headless (SPA/PWA/Hydrogen2) Integration

Welcome to our comprehensive tutorial on integrating Visually.io into your custom headless storefront. This guide will walk you through the process step by step.

Add Visually.io SDK

To get started, you need to include the Visually.io runtime dependencies in the <head> section of your index.html file. Be sure to place these script tags as close to the beginning of the <head> tag as possible. Replace <ANALYTICS_KEY> and <STORE_ALIAS> with the values provided to you by Visually.io.

<!--  index.html  -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

<!-- VISUALLY SDK -->
<script type="text/javascript" rel="preconnect prefetch"
src="https://live.visually-io.com/widgets/vsly-preact.min.js?k=<ANALYTICS_KEY>&e=2&s=<STORE_ALIAS>"></script>
<script type="text/javascript" rel="preconnect prefetch"
src="https://live.visually-io.com/v/visually-spa.js"></script>
<script defer type="application/javascript" src="https://live.visually-io.com/v/visually-a-spa.js"></script>
<!-- END OF VISUALLY SDK -->

</head>
<body>
<!-- ... -->
</body>
</html>

Notify our SDK on context changes:

To enable Visually.io to send analytics and track the user's journey throughout the session, you must set up the following hooks in your code:

declare global {
interface Window {
visually: {
     onCartChanged: (cart: CartBase) => void;
productChanged: (product: CurrentProduct) => void;
     localeChanged: (locale: string) => void;
     customerTagsChanged: (newTags: [string]) => void // shopify customer tags
currencyChanged: (currency: string) => void;
pageTypeChanged: (pageType: 'home'|'product'|'catalog'|'other') => void;
onUserIdChanged: (userId: string) => void; // signed in user id
visuallyConnect: (instrument: VisuallyInstrument) => void
}
}
}


For instance, when the current product changes, you should call: window.visually.productChanged(currentProduct)

Or when the current locale changes  you should call: window.visually.localeChanged('de')

Create a Visually.io Instrument

To allow Visually.io to interact with various components on your storefront, you need to create an object that adheres to the following interface:

interface VisuallyInstrument {
openCartDrawer: () => void;
closeCartDrawer: () => void;
addToCart: (variantId: string, quantity: number) => Promise<any>; // should create cart if none
cartClear: () => void;
cartAddAttributes: (attributes: {
attributes: Array<{ key: string, value: string }>
}, cb: (cart: any) => void) => void; // adds attributes to the cart
pageType: string;
currentProduct: CurrentProduct; // see type definition below
initialLocale: string; // eg: en|de|es
initialUserId: string; // signed in user id
initialProductId: number;
initialVariantId: number; // optional - only for PDP pages, current variant id
initialVariantPrice: number; // optional - only for PDP pages, current variant price
initialLocale: string; // optional - initial locale - 'en' by default
initialCurrency: string; // optional - initial currency - 'USD' by default
initialCart: CartBase; // initial cart if user has a cart, ( defined above )
customerTags: Array<string>; //OPTIONAL: SHPOIFY CUSTOMER TAGS
}
type BaseCartItem = {
variant_id: number,
quantity: number,
product_id: number,
price: number, // cents
compare_at_price?: number, // cents
handle: string,
selling_plan_allocation?: SellingPlanAllocation // optional - subscriptions info
}

interface SellingPlanAllocation {
selling_plan: SellingPlan
}

interface SellingPlan {
name: string
}

type CurrentProduct = {
variants: [
{
id: number,
price: number, // in cents
iq: number // inventory quantity
}
],
id: number,
oos: boolean,
price: number // max variant price in cents
}

After defining your instrument, invoke our bootstrap method during the initial page load at the root of your application:

useEffect(() => {
window.visuallyConnect(instrumentationTool)
// Please ensure that window.visuallyConnect is defined (window.visuallyConnect !== undefined).
}, []);


Here, instrumentationTool should implement the VisuallyInstrument interface. This ensures that Visually.io is properly integrated into your e-commerce SPA/PWA.

Please ensure that window.visuallyConnect is defined (window.visuallyConnect !== undefined).

Allowed domains

If the SPA has a security mechanism that allows the website to run only on specific domains

We require to add the following domains to the domains 'allow list'

- visually.io

- loomi.me

- vsly.local:8000


If you have any more questions or need any help, please don't hesitate to reach out to us.