Skip to content

Calcumate3D events

The calculator is a script embed in your page, so it talks to the page through standard DOM events. When it is loaded inside an iframe, it also mirrors the important moments to the parent frame with postMessage.

Direction Channel Who uses it
calculator → page CustomEvent on window, names calcumate:* script-tag embeds (same document)
calculator → page the four unprefixed Calcumate (original) CustomEvents (CalcumateInitialized, CalculationFinished, Booking, userDetails) sites written for Calcumate (original). See Calcumate (original) hooks in Calcumate3D
calculator → parent frame window.parent.postMessage({ type: 'CALCUMATE_*', … }) iframe embeds (cross-origin hosts)
page → calculator CustomEvent on window (RE-INIT, RootLoaded, calcumateLoad) or postMessage('RE-INIT') into the iframe re-loading the configuration, mounting late containers, filtering the recommended units

All calcumate:* events are CustomEvents dispatched on window; the data is in event.detail.

Event When event.detail
calcumate:ready the configuration loaded and the calculator is initialised. Fires on every successful load: first boot, RE-INIT, and a CalcumateGEO facility change (each is a full reload). { embedId }
calcumate:error the configuration could not be loaded and the visitor sees a retryable error (network error, invalid token). { code, message }
calcumate:blocked the configuration was refused and the visitor sees a blocking modal (domain_mismatch, plan / calculator disabled). { reason }
calcumate:state-changed every screen transition (see the state table below). { from, to, trigger }
calcumate:calculated a calculation produced recommendations (the calculating → result transition). { recommendationCount, bestMatch? } where bestMatch = { spaceUsedPct, unitCount, capacityVolumeCm3 } (omitted when the Calcumate service was unreachable and a local fallback packing is shown).
calcumate:cta-click the visitor pressed the results CTA (“See pricing” / your label). Fires at the click, before the lead form and before any redirect, whatever the CTA settings. { recommendationId, unitId, unitName, units: [{ id, name, count }] } — the recommendation the button belongs to, resolved to its unit identity.
Calcumate (original): Booking right after cta-click, and again after the lead-form submit { selectedCalculation, recommendation, items, location, cta: { url, label, resolvedUrl } }. See Booking
calcumate:lead-captured the lead form (Builder: Request lead details) was submitted. the cta-click detail + fields: [{ id, label, type, value }]

States and triggers (calcumate:state-changed)

Section titled “States and triggers (calcumate:state-changed)”
to Meaning
loading boot; assets loading (initial state — never a to, only a from)
intro the camera intro is playing (skipped for returning visitors and reduced-motion users)
idle the entry screen (presets or category grid)
staging the visitor is picking or editing items
calculating a calculation request is in flight
result recommendations are shown
error a calculation failed

Triggers: ASSETS_READY, INTRO_DONE, BROWSE, ITEM_ADDED, ITEM_CLEARED, CALCULATE, SUCCESS, ERROR, RETRY, ADJUST, EDIT, RESUME_RESULT, HOME. Only accepted transitions emit: adding a second item while already in staging is silent, and so is a trigger the current state ignores.

Typical sequences:

  • First visit: ready → loading → intro (ASSETS_READY) → intro → idle (INTRO_DONE).
  • Returning visitor: ready → loading → idle (ASSETS_READY).
  • Browsing + calculating: idle → staging (BROWSE) → staging → calculating (CALCULATE) → calculating → result (SUCCESS) + calculated.
  • A preset tile + Calculate: idle → staging (ITEM_ADDED) then the calculating pair.
  • Re-calculating from results: result → calculating (CALCULATE) → calculating → result.
  • Logo (home) from results: result → idle (HOME); Start again: idle → result (RESUME_RESULT).
  • Emptying the inventory from anywhere: … → idle (ITEM_CLEARED).
  • After a page refresh the calculator restores the visitor’s items and screen, so your page sees the normal sequence again (idle → staging, and the calculating pair for a restored result).
window.addEventListener('calcumate:ready', (e) => {
console.log('calculator ready', e.detail.embedId)
})
window.addEventListener('calcumate:state-changed', (e) => {
const { from, to, trigger } = e.detail
if (to === 'result') showBookNowBanner()
analytics.track('calculator_state', { from, to, trigger })
})
window.addEventListener('calcumate:calculated', (e) => {
const { recommendationCount, bestMatch } = e.detail
console.log(`${recommendationCount} options; best uses ${bestMatch?.unitCount} unit(s) at ${bestMatch?.spaceUsedPct}%`)
})
window.addEventListener('calcumate:cta-click', (e) => {
const { unitId, unitName, units } = e.detail
// e.g. pre-select the unit on your booking page, or route the visitor yourself
// when "Disable CTA redirection" is on in the Builder
})
window.addEventListener('calcumate:lead-captured', (e) => {
const { fields } = e.detail // [{ id, label, type, value }]
const email = fields.find((f) => f.type === 'email')?.value
})

These settings live in the Builder’s Advanced settings and Units steps.

Builder setting Effect on events
Disable CTA redirection ON cta-click (and the Calcumate (original) Booking) still fire; the calculator does not navigate. Use the event to route the visitor.
Request lead details ON cta-click → the lead form opens → lead-captured (and userDetails, then Booking again) on submit → then the redirect, if enabled. The lead is also posted to Calcumate and emailed to the configured recipients; lead data is never put in the CTA URL.
CTA URL params The redirect URL gets cm-qty, cm-id (+ cm-ids), cm-volume, cm-used-volume, cm-volume-unit (m3 / ft3), cm-recommendation + one {unitId}={count} pair per unit, according to the toggles; cm-location whenever a CalcumateGEO facility is selected. Independent of the events.
Unit “reserve url” (Builder, per unit) When the recommended unit has its own URL, the CTA opens that URL with no params instead of the global CTA URL.

Messages to the parent frame (iframe embeds)

Section titled “Messages to the parent frame (iframe embeds)”

When the calculator runs inside an iframe it also calls window.parent.postMessage(envelope, parentOrigin), where parentOrigin is taken from document.referrer. If the iframe is loaded with referrerpolicy="no-referrer" the origin is unknown and the messages are skipped.

Envelope: { type, payload, embedId, timestamp }.

type Mirrors payload
CALCUMATE_READY calcumate:ready —
CALCUMATE_ERROR calcumate:error { error }
CALCUMATE_STATE_CHANGED calcumate:state-changed { from, to, trigger }
CALCUMATE_CALCULATION_COMPLETE calcumate:calculated { recommendationCount }
CALCUMATE_CTA_CLICKED calcumate:cta-click the same detail
CALCUMATE_LEAD_CAPTURED calcumate:lead-captured the same detail
// parent page
window.addEventListener('message', (e) => {
// if (e.origin !== 'https://your-calculator-host.example') return
const msg = e.data
if (!msg || typeof msg.type !== 'string' || !msg.type.startsWith('CALCUMATE_')) return
if (msg.type === 'CALCUMATE_STATE_CHANGED' && msg.payload.to === 'result') showBookNowBanner()
})

The unprefixed Calcumate (original) events are not mirrored to the parent frame; Calcumate (original) never used postMessage either. Forward them from the framed page yourself if you need them there: the React Native pattern (injectedJavaScript + window.ReactNativeWebView.postMessage) applies to any iframe.

Events your page can send to the calculator

Section titled “Events your page can send to the calculator”
Event How Effect
RE-INIT window.dispatchEvent(new Event('RE-INIT')) — or, into an iframe, iframe.contentWindow.postMessage('RE-INIT', '*') / postMessage({ type: 'RE-INIT' }, '*') Reloads the configuration in place (fresh settings from the Builder) without re-mounting. Produces a new ready + the boot state-changed sequence. The snippet attributes are not re-read.
RootLoaded window.dispatchEvent(new Event('RootLoaded')) Re-scans the page for [data-calcumate] containers and mounts the new ones (SPAs, modals opened after the one-second auto-retry).
calcumateLoad window.dispatchEvent(new CustomEvent('calcumateLoad', { detail: ['unit-l'] })) Excludes those unit ids from the recommendations; [] re-enables all. A Calcumate (original) hook. Re-runs the calculation when results are on screen. window.listUnits lists the ids. See calcumateLoad.
data-disable-list-results="true" + RE-INIT attribute on the container Hides the recommendation list + CTA on the results screen; re-read on every RE-INIT. A Calcumate (original) hook. See data-disable-list-results.
// after your SPA navigates to a page that contains the snippet's <div>
window.dispatchEvent(new Event('RootLoaded'))
// after changing the calculator in the Builder, without reloading the page
window.dispatchEvent(new Event('RE-INIT'))
  • calcumate:ready is followed, in the same tick, by CalcumateInitialized; the pair precedes the first state-changed.
  • calcumate:calculated is always preceded by state-changed { to: 'calculating' } and state-changed { to: 'result' }, and followed by CalculationFinished.
  • calcumate:cta-click is followed by Booking; calcumate:lead-captured by userDetails and then a second Booking; the postMessage twin of each is sent right after the CustomEvent.
  • A CalcumateGEO facility pick is a full reload: expect a new ready / CalcumateInitialized (with the new facility in location) and no state-changed for the reset.
  • A load failure (error / blocked) emits nothing else until the visitor retries or the configuration is reloaded; a successful retry replays the full boot sequence.