Headless, PWA and Hyvä storefronts

What works when your storefront is not Magento's Luma theme, and how to add the chat widget yourself. Plan §12, §20 items 12–13. Only Luma and the Hyvä default theme have been tested (Luma on the local 2.4.7-p4 stack and in the 2026-09-26 version matrix; Hyvä 1.5.2 on 2.4.9 in that matrix — corrected 2026-09-27, this line said "only Luma"); everything on this page about other frontends is derived from the code and from Magento's core behaviour, and is marked where it depends on your frontend.

Two separate halves

  1. Server-side commerce integration — the Magento module and Conviro's backend talking to each other: events, sync jobs, live reads, the trust layer, AI actions. It does not care which frontend renders your shop.
  2. The chat widget — JavaScript in the shopper's browser that talks to Conviro directly. The module injects it into Magento-rendered pages; on a headless frontend you embed it yourself.

What works without Luma

CapabilityHeadless?Why
Catalog sync (product events, re-sync, nightly pull)yesProduct saves in the admin / REST API and the sync jobs run in Magento's backend and cron.
Stock sync (inventory.updated)yesAdmin, MSI API and import stock changes; cron.
Order eventsyes, for orders placed through Magento's quote submissionorder.placed listens to sales_model_service_quote_submit_success, which Magento's cart-management place-order path dispatches — GraphQL / REST checkouts included (core behaviour; not tested). Status, shipment and refund events come from admin/API saves.
Order history, customer import, repairyesCron jobs reading the database.
Live product, price, stock and order readsyesConviro calls the Magento REST API directly.
Trust layer, grounding, AI action policyyesBackend-side.
payment.failedyes, when placing the order fails inside Magento's quote submissionsales_model_service_quote_submit_failure (core; not tested).
customer.created (lead on registration)dependsListens to customer_register_success, which Luma's registration controller dispatches. Whether your headless registration path dispatches it depends on that code (not tested).
cart.updated (cart recovery)usually noListens to checkout_cart_save_after, dispatched by Magento's storefront cart model. Cart changes made through the REST / GraphQL cart APIs do not dispatch it (core behaviour; not tested).
Cart-recovery e-mail linkset itSet Sync Settings › Cart page URL (headless stores) (store view scope) to your storefront's cart page; the module sends it with every cart.updated. Empty = the store view's own Magento checkout/cart URL.
Product linkscheckproductUrl in product events (and the knowledge base's URL line, the product cards in chat) is Magento's product URL on the store's base URL, not your frontend's route.
Product-view / add-to-cart tracking eventsnoNot built in 1.4.0 (plan §12).

What does not apply

Embedding the widget on a headless frontend

  1. Get the snippet and public key. Conviro dashboard › Chatbots › (your bot) › Setup, final step. The public key is also shown under Chatbot › Channels, and after connecting it is stored in Magento as conviro_aichat/general/public_key (the wizard fills it from the chatbot you approved). General install notes: undefined (../../../docs/guides/WIDGET_INSTALL.md).
  2. Pass the Magento store view so answers use that store view's prices, stock, currency and language. Use the Magento store view code exactly (Magento's REST routing is case-sensitive; the code must name an active store view that is selected in wizard step 4, otherwise Conviro answers from the default store view):
    <script>
    (function(w,d,s,o,f,js,fjs){
      if(d.getElementById(o))return;
      w['ChatWidget']=o;w[o]=w[o]||function(){(w[o].q=w[o].q||[]).push(arguments)};
      js=d.createElement(s);fjs=d.getElementsByTagName(s)[0];
      js.id=o;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs);
    }(window,document,'script','cw','https://cdn.conviro.io/widget/widget.iife.js'));
    cw('init', {
      publicKey: 'pk_…',
      apiUrl: 'https://api.conviro.io',
      storeView: { code: 'de_store', locale: 'de_DE', language: 'de' },
      language: 'de'
    });
    </script>
  3. Identify a logged-in shopper from the browser (never server-side into a cached page), so the assistant can greet them by name (display only — it never opens an order; order answers still need the order number and checkout e-mail, or, from 1.5.0, a verified identity — see below):
    cw('identify', { id: String(customer.id), name: customer.fullName, email: customer.email });

    This sends the customer's id, name and e-mail to Conviro, which stores them with the chat session (Privacy). Call it again after login; do not call it for guests.

  4. Content Security Policy. Allow https://cdn.conviro.io (script, style, font, img, frame), https://api.conviro.io (script, connect, img) and wss://api.conviro.io (connect) — the same hosts as the module's csp_whitelist.xml.
  5. Consent. The Magento module's own template loads the widget without asking a consent manager. On your frontend, decide per your consent requirements: load the snippet only after consent (from your CMP's callback), or use Conviro's consent-gated loader described in undefined (../../../docs/guides/CUSTOMER_INTEGRATION.md) (not tested with Magento).

Hyvä and Hyvä Checkout

The module ships a layout handle for Hyvä Checkout (hyva_checkout_index_index.xml) and its widget template is plain JavaScript (no RequireJS, Knockout or jQuery; a static file, Conviro_AiChat::js/widget-loader.js). For the logged-in customer it reads the customer and conviro-customer sections from Magento's mage-cache-storage local-storage entry (or Hyvä's private-content-loaded event), falling back to one read of customer/section/load when they have not arrived; a guest page makes no identity request. Tested (version matrix, 2026-09-26): the Hyvä default theme 1.5.2 on Magento 2.4.9 with the Luma checkout fallback (hyva-themes/magento2-luma-checkout 1.1.7) — storefront walk in production mode, full-page-cache privacy, consent and attribution with Hyvä's cookie banner, widget identity. Hyvä Checkout has not been tested (a licensed product). See Supported versions.

Signed customer identity on other frontends (1.5.0, unreleased)

1.5.0 (unreleased), tested 2026-09-27/28 in a real browser on Luma and on the Hyvä default theme 1.5.2 (Magento 2.4.7-p9), not on a headless storefront. What the feature is: Signed customer identity and My orders.

The bridge needs a Magento storefront session on the store view's own origin: the widget asks the store's GET /conviro/identity/bootstrap with the browser's Magento session cookie, same origin, and Magento signs only for the customer that session belongs to (how the request is checked).

StorefrontSigned identity / My orders
Luma, pages rendered by MagentoWorks (the module's loader registers the identity provider). Tested in a real browser, including sign-out in another tab.
Hyvä theme (Magento renders the pages)Works — the loader handles Hyvä's private-content-loaded for sign-out and account switch. Tested on Hyvä 1.5.2 with Magento 2.4.7-p9, also behind Varnish.
Hyvä Checkoutnot tested (licensed).
Headless / PWA on another origin (PWA Studio, Next.js, Vue Storefront …) with GraphQL / REST customer tokensDoes not work. There is no Magento session cookie on that origin, and the bootstrap refuses cross-site requests and foreign Origins. The widget stays in the guest mode: greeting by name if you call cw('identify', …) (display only), order lookup with order number + checkout e-mail.
A frontend on the same origin as the store view that keeps Magento's storefront sessionPossible in principle, not supported or tested in 1.5.0: it would have to register its own provider with the widget (cw('identityProvider', fn), where fn({nonce, widgetSessionHash}) calls the bootstrap with X-Requested-With: XMLHttpRequest, credentials: 'same-origin', cache: 'no-store', rejects an answer whose nonce is not the one sent, and never resolves null) and call cw('identityRevoke', 'CUSTOMER_LOGGED_OUT' | 'ACCOUNT_SWITCHED') on sign-out / account switch. Ask Conviro before relying on it.

What never changes on any frontend: cw('identify', …) and any id or e-mail the page passes are display only and never open an order; a guest never makes an identity request; nothing about the shopper may be rendered into cacheable HTML.

Checklist for a headless store