New AI Sign Maker: Turn any logo into a quote in 2 minutes
gradient background image

Headless Commerce Product Configurator | Sign Customiser

Headless Commerce logo
Sign Customiser logo

Add sign product customization to your headless ecommerce stack. API-first configurator for React, Next.js, Vue, and Shopify Hydrogen. Embed in minutes.

Sign Customiser works with any headless commerce setup. Embed via iframe and communicate through the postMessage API. No vendor lock-in, no styling conflicts.

Quick Start

Get a working product customiser in your headless storefront.

1. Create Your Account

Register at web.signcustomiser.com/register. Free tier available.

2. Create a Customiser

From your dashboard, click Get Started and choose a sign type (neon, acrylic, metal, etc.). Configure your pricing rules and options.

3. Get Your Embed Code

In your dashboard, navigate to your customiser settings to get your unique iframe embed code. See how to find your customiser ID.

4. Add the Embed Code

Paste the iframe into your page:

<iframe
src="https://web.signcustomiser.com/embed/YOUR_CUSTOMISER_ID"
width="100%"
height="600"
frameborder="0"
allow="clipboard-write"
id="sign-customiser-iframe"
></iframe>

Replace YOUR_CUSTOMISER_ID with the ID from your dashboard.


Handling Product Creation Events

When a customer completes their design and clicks “Add to Cart”, Sign Customiser sends a message to your page. Listen for it with the postMessage API:

window.addEventListener('message', (event) => {
// Verify the message origin for security
if (event.origin !== 'https://web.signcustomiser.com') return;
if (event.data.type === 'onProductCreated') {
const productData = event.data;
// Your custom add-to-cart logic here
console.log('Product created:', productData);
// After processing, hide the loading screen
const iframe = document.querySelector('#sign-customiser-iframe');
iframe.contentWindow.postMessage(
{ type: 'hideLoadingScreen' },
'https://web.signcustomiser.com'
);
}
});

The onProductCreated event contains all product details including dimensions, pricing, and preview images.


Framework Examples

components/SignCustomiser.tsx
'use client';
import { useEffect, useRef } from 'react';
interface SignCustomiserProps {
customiserId: string;
onProductCreated: (data: any) => void;
}
export function SignCustomiser({ customiserId, onProductCreated }: SignCustomiserProps) {
const iframeRef = useRef<HTMLIFrameElement>(null);
// Store callback in ref to avoid re-running effect when it changes
const callbackRef = useRef(onProductCreated);
callbackRef.current = onProductCreated;
useEffect(() => {
function handleMessage(event: MessageEvent) {
// Verify the message origin for security
if (event.origin !== 'https://web.signcustomiser.com') return;
if (event.data.type === 'onProductCreated') {
callbackRef.current(event.data);
// Hide loading screen after processing
iframeRef.current?.contentWindow?.postMessage(
{ type: 'hideLoadingScreen' },
'https://web.signcustomiser.com'
);
}
}
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);
return (
<iframe
ref={iframeRef}
src={`https://web.signcustomiser.com/embed/${customiserId}`}
width="100%"
height="600"
frameBorder="0"
allow="clipboard-write"
/>
);
}
<template>
<iframe
ref="iframeRef"
:src="`https://web.signcustomiser.com/embed/${customiserId}`"
width="100%"
height="600"
frameborder="0"
allow="clipboard-write"
/>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
const props = defineProps({
customiserId: String
});
const emit = defineEmits(['productCreated']);
const iframeRef = ref(null);
function handleMessage(event) {
// Verify the message origin for security
if (event.origin !== 'https://web.signcustomiser.com') return;
if (event.data.type === 'onProductCreated') {
emit('productCreated', event.data);
// Hide loading screen
iframeRef.value?.contentWindow?.postMessage(
{ type: 'hideLoadingScreen' },
'https://web.signcustomiser.com'
);
}
}
onMounted(() => {
window.addEventListener('message', handleMessage);
});
onUnmounted(() => {
window.removeEventListener('message', handleMessage);
});
</script>
// app/routes/products.$handle.tsx
import { useLoaderData } from '@shopify/remix-oxygen';
import { useEffect, useRef } from 'react';
export default function Product() {
const { product, customiserId } = useLoaderData();
const iframeRef = useRef<HTMLIFrameElement>(null);
useEffect(() => {
function handleMessage(event: MessageEvent) {
// Verify the message origin for security
if (event.origin !== 'https://web.signcustomiser.com') return;
if (event.data.type === 'onProductCreated') {
// Add to Hydrogen cart
console.log('Product created:', event.data);
iframeRef.current?.contentWindow?.postMessage(
{ type: 'hideLoadingScreen' },
'https://web.signcustomiser.com'
);
}
}
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);
return (
<div>
<h1>{product.title}</h1>
<iframe
ref={iframeRef}
src={`https://web.signcustomiser.com/embed/${customiserId}`}
width="100%"
height="600"
frameBorder="0"
allow="clipboard-write"
/>
</div>
);
}

For native Shopify integration with automatic product sync, see the Shopify app.


Custom API Integration

For advanced integrations, you can sync products and orders directly with the Sign Customiser API.

Product Sync API

When a product is created in the customiser, sync it with your backend:

Terminal window
POST https://web.signcustomiser.com/api/customisers/{customiserId}/products
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
{
"product_id": "your-product-id",
"cart": {},
"price_breakdown": {},
"custom_background_path": "url",
"custom_background_original_path": "url",
"product_type_paths": {},
"logo_original_path": null
}

Order Submission API

When an order is placed, notify Sign Customiser:

Terminal window
POST https://web.signcustomiser.com/api/orders
Authorization: Bearer YOUR_API_TOKEN
Content-Type: application/json
X-API-Client: generic
{
"order_id": "123456",
"order_number": "ORD-1001",
"products": [
{ "id": "product-id-from-sync" }
]
}

See the full Custom API Integration guide for webhook setup, signature verification, and complete payload schemas.


Why Headless?

Traditional product configurators cause three problems in headless architectures:

SSR conflicts. Most configurators call browser APIs on load, causing hydration mismatches.

Styling collisions. Injected CSS clashes with your design system.

Data silos. Getting product data out requires workarounds.

Sign Customiser avoids these issues. The iframe provides complete isolation, and the postMessage API gives you full control over the data flow.


What You Get


Shopify

Add Sign Customiser to your store today

Install Now