Skip to main content

Launch your first experience from a custom storefront

In this tutorial you will build a single HTML page with a "Personalize" button. Clicking it launches an activation in a Spiff Commerce-hosted overlay, and when the customer finishes, you receive their bundle and turn each design into a cart line item.

It uses the Hosted Experience API, so you don't need to build any UI yourself. The same steps apply to any storefront where you control the page, such as a headless or custom-built store.

Before you begin​

You will need:

  • An application key, from your integration in the Spiff Commerce Hub.
  • An activation ID, for the activation you want customers to launch.
  • The region your Spiff Commerce account is hosted in (au or us).
  • Your presentment currency as an ISO 4217 code, such as USD.

1. Create the page and load the script​

Create index.html with a button, and load the Hosted Experience script in the <head>. The script is always loaded from the US URL, whichever region your account is in.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My store</title>
<script src="https://assets.us.spiffcommerce.com/api.js"></script>
</head>
<body>
<button id="personalize">Personalize</button>
<script src="./spiff.js"></script>
</body>
</html>

You will write spiff.js over the next steps.

2. Wait for the API and set your region​

The script defines window.Spiff asynchronously and announces it with a SpiffApiReady event. Create spiff.js and wait for it.

function onSpiffReady() {
// Your account's region. Without this the API defaults to Australia (AU).
window.Spiff.setRegion("us");

document.getElementById("personalize").addEventListener("click", launchExperience);
}

if (window.Spiff) {
onSpiffReady();
} else {
window.addEventListener("SpiffApiReady", onSpiffReady);
}

Checking window.Spiff first covers the case where the script finished loading before your code ran.

warning

Call setRegion before launching anything. Region changes apply to the whole page and cannot be reversed. See Hosted Experience API for details.

3. Launch the activation​

Add launchExperience. A bundle experience needs bundleMode: true, your application key, and the activation ID, which is passed as a query parameter.

function launchExperience() {
const experience = new window.Spiff.HostedExperience({
bundleMode: true,
applicationKey: "<Your application key>",
presentmentCurrency: "USD",
queryParams: { activationId: "<Your activation ID>" },
});

experience.on("complete", handleComplete);
experience.on("quit", handleQuit);

experience.execute();
}

Two details matter here:

  • Register both complete and quit before calling execute(). Only one experience can be open at a time, and the page is only marked free again when one of these handlers runs.
  • Create a new HostedExperience for every launch. An instance can only be executed once.

execute() shows a loading screen, then the experience, in a full-screen overlay. To render inside an element on your page instead, pass embedElement. See Hosted Experience API for all the options.

4. Handle the customer leaving​

If the customer closes the experience without finishing, quit is called with null. The overlay closes itself, so there is usually nothing to clean up.

function handleQuit() {
console.log("The customer left without finishing.");
}

5. Turn the finished bundle into cart line items​

When the customer finishes, complete is called with their bundle. It contains a bundleId and an items array with one entry per design. Each item has a transactionId, the reference to that design, along with the product to add to your cart.

Replace addLineItemsToCart with a call to your own cart.

async function handleComplete(result) {
const lineItems = result.items.map((item) => ({
// The product and variant in your store that this design is for.
productId: item.externalCartProductId,
variantId: item.externalCartProductVariantId,
quantity: item.quantity,
// Keep these against the line item. They are the link back to the design.
spiffBundleId: result.bundleId,
spiffTransactionId: item.transactionId,
// A preview image of the design, to show in the cart.
imageUrl: item.previewImage,
}));

await addLineItemsToCart(lineItems);
window.location.href = "/cart";
}

async function addLineItemsToCart(lineItems) {
// Replace with your own cart implementation.
await fetch("/api/cart/items", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ items: lineItems }),
});
}
warning

You must store each transactionId against the line item in your cart, and again on the order your store creates. It is how Spiff Commerce associates an order with the design the customer made.

The bundleId is worth keeping too, as it lets the customer come back and edit their designs later. See Reopen and edit a saved design.

How designs are added to the cart​

The result also has a cartAddMode that controls how the bundle's designs map to cart lines:

ModeBehavior
DefaultConsolidate products into as few line items as possible.
FirstTransactionAdd only the first design.
OneToOneAdd every design as its own line item, with no consolidation.

The code above adds every design as its own line, which matches OneToOne. Branch on result.cartAddMode if your theme sets another mode. externalCartProductId and externalCartProductVariantId are only set when the product is linked to a product in your store. Items can also carry additionalExternalProductId, additionalExternalVariantId and designExternalVariants, which describe further products to add alongside the design.

6. Try it​

Serve the folder with any static server, for example npx serve ., open the page and click Personalize. You should see the loading screen, then your activation. Finish a design and check that your addLineItemsToCart function receives one item per design, each with a transactionId.

Next steps​