Clueless Widget Integration

Launch the Clueless shopping assistant, configure script parameters, and connect your product feed.

Clueless Widget Integration Guide

Bring the Clueless conversational assistant to your storefront in just a few minutes. This guide covers the loader snippet, optional configuration flags, diagnostics, and how to ingest your product catalog so the assistant can answer inventory questions with confidence.

1. Add the loader snippet

Embed the loader script on every page that should host the widget. We recommend placing it as close to the end of the <head> element as possible so it boots as soon as the DOM becomes interactive.

Minimal loader
<script
  async
  data-clueless-widget
  data-merchant-key="your-merchant-key"
  src="https://widget.clueless.chat/widget/loader.iife.js"
></script>

The loader URL is stable — you never need to update your embed code to receive the latest widget changes.

Where to place the script

  • Direct HTML / platforms with template access – Paste the snippet right before </head> in your global layout (e.g. Shopify theme.liquid, WooCommerce header.php, Custom React/Vue SSR template).

  • Google Tag Manager – Create a Custom HTML tag, paste the snippet, trigger on All Pages, and publish. The loader works with both standard and consented container deployments.

  • Single-page applications (React, Vue, Next.js, etc.) – Dynamically inject the script once after hydration:

    const script = document.createElement("script");
    script.async = true;
    script.setAttribute("data-clueless-widget", "");
    script.setAttribute("data-merchant-key", "your-merchant-key");
    script.src = "https://widget.clueless.chat/widget/loader.iife.js";
    document.head.appendChild(script);

2. Generate a preconfigured snippet

Use the generator to pre-fill the required merchant key and any optional parameters before handing the code to your developers or agency partners.

Embed Code Generator

<script
  async
  data-clueless-widget
  data-merchant-key="your-merchant-key"
  data-mode="fab"
  src="https://widget.clueless.chat/widget/loader.iife.js"
></script>

Where to add this code:

  • Direct HTML: Add to your website's <head> section
  • Google Tag Manager: Create a Custom HTML tag with "All Pages" trigger
  • React/Vue/Angular: See the integration guide for framework-specific instructions

3. Loader attributes & query parameters

Customize behaviour by adding data attributes to the <script> tag. All options also support query-string equivalents on the loader URL.

AttributeTypeDefaultWhen to use
data-merchant-keystringRequiredMerchant identifier that tells the CLJ backend which catalog/config to use. This should be part of every production embed snippet.
data-server-urlURLunsetLegacy backend base URL. When set, the loader derives <server-url>/chat; new embeds should prefer data-chat-endpoint. ?serverUrl=https://api.example.com also works.
data-chat-endpointURLhttps://clueless-backend.gcp.clueless.chat/chatProvide a fully qualified chat endpoint when you are explicitly testing a different backend.
data-modefab | floating | expandedfabControl the initial resting state. fab is the safe default for merchant sites with sticky mobile CTAs.
data-launcherauto | noneautoHide the built-in FAB/floating launcher when your page owns the launch button. The widget still boots and can be opened through host triggers or window.cluelessWidget.
data-primary-selectorgender | nonemerchant defaultOptional override for the first-class selector shown above the prompt. If omitted, the widget uses the merchant-specific default from GET /widget/experience?merchant=<merchantKey>.
data-fab-color-schemedefault | inverteddefaultSwap the resting FAB from the default frosted light shell to a solid trigger-colored treatment. Useful when the host page background makes the default FAB disappear.
data-fab-positionpreset stringautoAnchor the resting FAB independently of the opened floating prompt. When omitted, the loader defaults to middle-right on compact viewports and bottom-right on larger ones.
data-floating-positionpreset stringbottom-centerAnchor the floating prompt independently of the FAB. This preserves the old bottom-centered dock behavior by default.
data-fab-offset-inline / data-fab-offset-blockCSS lengthunsetNudge the FAB anchor without abandoning preset-based placement.
data-floating-offset-inline / data-floating-offset-blockCSS lengthunsetNudge the floating prompt anchor independently of the FAB.
data-cssURL path/widget.cssServe a tenant-specific stylesheet for the iframe shell. Useful for brand-specific theming.
data-iframeURL<loader-origin>/app/Override the iframe location (e.g. QA builds hosted on Vercel).
data-debugbooleanfalseEnable verbose console logging. Setting the attribute with no value or data-debug="true" turns logging on; ?debug=1 does the same.
data-ga-id / data-ga-secretstringsnullWire Google Analytics 4 measurement IDs and secrets so widget events forward into your GTM data layer after consent.

Tip: the loader copies all data-* attributes onto its Shadow DOM host. You can safely set custom attributes for your own telemetry as long as they are prefixed with data-.

Today the only built-in selector is gender. Disabling it with data-primary-selector="none" leaves the stock/inventory controls intact and avoids biasing the assistant toward a default gender, while omitting the attribute lets the merchant backend decide the default. Separately, data-fab-color-scheme="inverted" switches the resting launcher to the merchant trigger color when the default frosted shell needs more contrast.

4. Programmatic control and lifecycle events

Once the iframe signals readiness, the loader exposes a controller at window.cluelessWidget:

window.cluelessWidget?.open();
window.cluelessWidget?.close();
window.cluelessWidget?.toggle();
window.cluelessWidget?.minimize();
window.cluelessWidget?.setMode("floating");
window.cluelessWidget?.open({ mode: "expanded", triggerId: "hero-style" });
window.cluelessWidget?.prompt({
  text: "Create a full outfit around this product",
  mode: "expanded",
  submit: true,
  triggerId: "pdp-style-submit",
});
const context = window.cluelessWidget?.getContext();

open() opens the primary chat surface. With data-launcher="none", open() defaults to expanded because there is no Clueless-owned resting launcher. Pass { mode: "floating" } when a host control should reveal the compact prompt instead. close() steps back one level. minimize() returns to the resting launcher, or hides the frame again when data-launcher="none" is active. postMessage() is available for typed widget protocol messages, but ordinary integrations should use the controller helpers above.

You can control the widget from ordinary host-page elements by adding Clueless data attributes. The loader listens at the document level, so elements rendered later by a CMS, tag manager, or SPA route still work.

Keep the default launcher and add a product CTA:

Extra host trigger
<button
  type="button"
  data-clueless-widget-trigger="open"
  data-clueless-widget-mode="expanded"
  data-clueless-widget-trigger-id="pdp-style-this"
>
  Style this product
</button>

Hide the built-in launcher and use only merchant-owned controls:

No built-in launcher
<script
  async
  data-clueless-widget
  data-merchant-key="your-merchant-key"
  data-launcher="none"
  src="https://widget.clueless.chat/widget/loader.iife.js"
></script>

<button
  type="button"
  data-clueless-widget-trigger="open"
  data-clueless-widget-mode="expanded"
>
  Ask our stylist
</button>

Submit a product-specific prompt from a host element:

Host prompt submit
<button
  type="button"
  data-clueless-widget-trigger="prompt"
  data-clueless-widget-mode="expanded"
  data-clueless-widget-prompt="Create a full outfit around this product"
  data-clueless-widget-submit="true"
  data-clueless-widget-trigger-id="pdp-outfit-submit"
>
  Build an outfit
</button>

Supported trigger actions are open, toggle, close, minimize, set-mode, and prompt. Prompt triggers require data-clueless-widget-prompt; data-clueless-widget-submit="true" sends immediately, while any other value only prefills the prompt. Prompt triggers can include data-clueless-widget-product-id to send chat metadata.productId. For non-button elements, add role="button" and tabindex="0" so Enter and Space work. Anchor triggers prevent navigation by default; set data-clueless-widget-prevent-default="false" when the link should still navigate.

Product suggested prompts

On product pages, add a placeholder when you want Clueless to show product-specific question buttons. The loader fetches questions lazily when the block approaches the viewport, then renders host prompt buttons into the placeholder. Clicking a question opens the widget in expanded mode and submits that question through the same controlled prompt path shown above.

Suggested product questions
<div
  data-clueless-suggested-prompts
  data-clueless-suggested-prompts-title="Vanliga frågor"
></div>

By default, the loader resolves the product id from page context. On product pages this includes JSON-LD Product markup, using sku or productID when present. Add data-clueless-product-id only when the storefront does not expose usable product markup or when you need to force a specific backend article id. The request uses the same backend origin as chat and sends Accept-Language from data-clueless-suggested-prompts-language, page context locale, document language, or browser language.

Suggested question clicks forward the same resolved product id as chat metadata.productId. When that id resolves to a backend article, the assistant treats that product as already shown and can answer suggested questions from the current product data.

The placeholder receives data-clueless-suggested-prompts-state="idle|loading|ready|empty|error|skipped" and aria-busy while loading so storefront code can style or inspect it. If no buttons appear, verify that the product id exists, that the backend has related questions for the article, and that the storefront origin is allowed by backend CORS.

Listen for lifecycle events if you need to coordinate UI changes or analytics:

  • clueless-widget-ready – Fired after the iframe confirms it mounted successfully. event.detail.controller contains the same controller instance shown above.
  • clueless-widget-error – Fired if the iframe fails to boot (network errors, authorization, CSP violations).
window.addEventListener("clueless-widget-ready", (event) => {
  console.info("Widget ready", event.detail.controller.getContext());
});

window.addEventListener("clueless-widget-error", (event) => {
  console.error("Widget failed to load", event.detail);
});

Product card navigation (SPA-friendly)

When a shopper clicks a product card inside the widget, the loader emits a cancelable event on the host window:

  • Event name: clueless-widget-navigate
  • event.detail.url: fully-qualified URL that includes utm_source=clueless and utm_medium=widget (we overwrite utm_source if it already exists)
  • event.detail.action: "push" or "replace"
  • event.detail.source: "product_card"

If your storefront is an SPA (Next.js / React Router / Vue Router / etc.), listen for this event, call event.preventDefault(), and route using your framework so the page updates without reloading the widget.

SPA navigation handler
window.addEventListener("clueless-widget-navigate", (event) => {
  const { url, action, source } = (event as CustomEvent<{
    url?: string;
    action?: "push" | "replace";
    source?: string | null;
  }>).detail ?? {};

  if (source !== "product_card" || !url) {
    return;
  }

  const target = new URL(url);

  // Tell the widget loader "we'll handle this navigation"
  event.preventDefault();

  // Example (React Router / your router API here):
  // navigate(`${target.pathname}${target.search}${target.hash}`, { replace: action === "replace" });
});

If you don’t prevent the default, the loader will fall back to window.location.* navigation (MPA-safe). For MPAs, the widget restores its open state + chat state after the page transition.

Cross-document view transitions (optional)

If your storefront uses same-origin server navigations, you can progressively enhance widget-originated PDP transitions with the browser View Transitions API. This is a host-page opt-in, not a widget-only feature.

Add this to the merchant theme CSS on pages that participate in the transition:

Enable cross-document view transitions
@view-transition {
  navigation: auto;
}

That alone is enough for browsers with cross-document View Transition support to animate same-origin page navigations triggered by the widget's default window.location.* fallback.

If you want to route widget-originated navigations differently from ordinary page clicks, attach a host-side listener and mark the transition before navigating:

Optional early host helper
<script>
  window.addEventListener("clueless-widget-navigate", (event) => {
    const detail = event.detail ?? {};
    if (detail.source !== "product_card" || !detail.url) {
      return;
    }

    sessionStorage.setItem(
      "clueless-widget-transition",
      JSON.stringify({
        kind: "product_card",
        action: detail.action ?? "push",
        url: detail.url,
        at: Date.now(),
      })
    );
  });
</script>

Important limitations:

  • The widget iframe is cross-origin, so browsers cannot do a native shared element transition from a product card inside the widget to a PDP image on the merchant page.
  • The realistic first step is a page-level transition between same-origin documents.
  • Advanced typed transitions using pageswap / pagereveal require early host scripts in the merchant document, not the async widget loader.
  • Unsupported browsers will keep the current behavior automatically.

5. Verify your installation

  1. Open the site in an incognito window and confirm the widget loads as a compact FAB instead of a full-width prompt dock.
  2. Click the FAB and ask “Show me something new from your favourite brand” to validate that conversations start.
  3. Open DevTools (top-level browsing context) and run window.cluelessWidget?.getContext() – you should see product/route metadata for the current page.
  4. If the merchant has a sticky mobile CTA, move the resting FAB with data-fab-position or the FAB offset overrides so it sits outside that collision zone without disturbing the floating prompt dock.
  5. Check for console warnings or CSP violations; if you see blocked resources, allow requests to widget.clueless.chat and your configured API host.
  6. Inspect your GTM dataLayer for entries with event: "clueless_widget_event" and the expected event_name when the assistant opens, closes, submits prompts, or navigates.

6. Troubleshooting checklist

  • Widget never appears: verify the script tag includes data-clueless-widget and data-merchant-key, there are no duplicate CSP rules, and the script is not blocked by an ad blocker. Adding data-debug will print loader progress to the console.
  • Stuck after opening the widget – confirm the site can reach your Clueless chat host (no mixed-content or firewall blocks) and that any optional data-chat-endpoint override is correct.
  • Clicking product card links fails: for SPAs, ensure you handle clueless-widget-navigate and call your router; for MPAs, ensure your site permits window.location.* redirects from scripts and that PDP URLs exist in your product feed (see next section).
  • Multiple widgets render: only include one loader snippet per page. Remove older snippets from tag managers or theme partials.

7. Keep the product feed in sync

The assistant relies on a structured product feed so it can recommend in-stock items. Provide at least one of the following to the Clueless team:

  1. Hosted feed URL – We accept Google Merchant-style RSS/Atom XML feeds. Each item should include id, title, description, link, price, availability, image_link, brand, product_type, and gender indicators when available.
  2. Locale configuration – If you sell in multiple markets, supply price/locale multipliers or let us know which currency to prioritize. We normalize prices to cents internally.
  3. Authentication, if required – Share HTTP basic credentials or signed URLs if the feed is not publicly accessible.

Once your feed is ready:

  1. Sign in to the Clueless Merchant Admin and open Catalog → Product Feed.
  2. Paste the secure feed URL, choose the default currency, and save.
  3. We queue the ingestion job immediately—no API calls or emails required.

You can revisit the same screen to see the latest sync status, next scheduled crawl, and any validation errors we detected (missing prices, unreachable images, etc.). Failed rows can be downloaded as a CSV for quick remediation.

8. What happens next?

  • Dashboard analytics will start populating as soon as customers interact with the assistant.
  • You can customize greetings, suggested prompts, and brand priorities from the Clueless dashboard or through your customer success manager.
  • As your product feed changes, e.g. due to changes in inventory or new products being added, the ingestion will re-run using a nightly scheduler, so the assistant always stays up to date.

Still have questions? Reach us at support@clueless.chat – we reply within one business day.