Skip to main content
This guide walks through the most common setup: embedding the Checkout Widget on a product page. If you’re collecting card details for a custom payment flow, jump to the Card Element guide instead.

Prerequisites

  • A Widget ID from the Henry Dashboard
  • A product URL (any publicly accessible product page)

Setup

1

Install the SDK

npm install @henrylabs/js
Or load via CDN - no build step required:
<script src="https://cdn.jsdelivr.net/npm/@henrylabs/js"></script>
When loaded via CDN, use window.Henry instead of the ES module import.
2

Add a container element

<div id='checkout-container'></div>
3

Mount the Checkout Widget

import Henry from "@henrylabs/js";

const el = Henry.createCheckoutElement("#checkout-container", {
  widgetId: "widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  items: [
    {
      link: "https://www.nike.com/t/some-product/ABC-123",
      quantity: 1,
      variant: { size: "10", color: "White" },
    },
  ],
});

End-to-end walkthrough

Step 1 - Mount the widget

createCheckoutElement takes a CSS selector (or DOM element) and an options object. Henry renders the widget inside your container immediately.
import Henry from '@henrylabs/js';

const el = Henry.createCheckoutElement('#checkout-container', {
	widgetId: 'widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
	items: [
		{
			link: 'https://www.nike.com/t/air-max-270/AH8050-002',
			quantity: 1,
			variant: { size: '10', color: 'Black' },
		},
	],
	display: {
		size: 'compact', // "full" | "comfortable" | "compact" | "bubble" | "direct"
		theme: 'system', // "light" | "dark" | "system"
	},
});
See Checkout Widget for the full list of display sizes and what each looks like.

Step 2 - Listen for checkout events

Use .on() to respond when the buyer completes or closes checkout:
el.on('checkout-complete', ({ status, order }) => {
	console.log('Checkout finished:', status);
	// show a confirmation UI, redirect, etc.
});

el.on('checkout-closed', ({ source }) => {
	// source is "user" (buyer closed) or "system" (programmatic close)
	console.log('Checkout closed by:', source);
});

Step 3 - Clean up

Call .destroy() when the widget is no longer needed to unmount it and remove all listeners:
el.destroy();

React

Use a ref guard to prevent double-mounting in React Strict Mode:
import { useEffect, useRef } from 'react';
import Henry from '@henrylabs/js';

function ProductPage() {
	const initialized = useRef(false);

	useEffect(() => {
		if (initialized.current) return;
		initialized.current = true;

		const el = Henry.createCheckoutElement('#checkout-container', {
			widgetId: 'widget_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
			items: [{ link: 'https://www.nike.com/t/air-max-270/AH8050-002', quantity: 1 }],
			display: { size: 'compact', theme: 'dark' },
		});

		el.on('checkout-complete', ({ status, order }) => {
			console.log('Done:', status, order);
		});

		return () => el.destroy();
	}, []);

	return <div id='checkout-container' />;
}

Next steps

Checkout Widget

All display modes, settings, and events for the checkout widget

Card Element

Embed a secure card input for custom payment flows