Client Events & Callbacks
When an embedded engagement runs (script tag, iframe, or the managed BricqsEngagement component), the runtime notifies your page about what happened via postMessage. This page is the complete, exact list of those client-side messages and how to consume them on each integration path.
points:awarded) are CLIENT callbacks emitted by the embed runtime into your page, documented here. Dot names (points.awarded.v1) are SERVER events delivered to your backend via webhooks and the SSE stream, published in the machine-readable event catalog. They are different surfaces with different payloads.How callbacks reach you
| Integration | Mechanism | Syntax |
|---|---|---|
| Script tag | Global window.Bricqs (capital B) with short alias names | Bricqs.on('points', handler) |
| Raw iframe | postMessage: { source: 'bricqs', type, payload } | window.addEventListener('message', ...) |
| React SDK (managed) | Callback props on BricqsEngagement | <BricqsEngagement onPointsAwarded={...} /> |
| Headless hooks | No postMessage involved: hooks return data and refresh; live updates via useBricqsStream (server events) | usePoints(...) |
Message reference
This is the complete emission surface. Every message has the shape { source: 'bricqs', type: '<type>', payload: {...} } and is posted only to your page’s origin (never *). Payload fields below are exhaustive; the embellished fields in older docs (session ids, rarity, scores) do not exist on these messages.
| postMessage type | Script-tag alias | React prop | Payload |
|---|---|---|---|
engagement:ready | ready | onReady | { engagementId } |
activity:completed | activity:complete | onActivityComplete | { activityId, activityType, result?, actionResults? } |
points:awarded | points | onPointsAwarded | { points, newBalance } |
tier:changed | tier | onTierChanged | { tierCode, tierName, tierLevel } |
badge:unlocked | badge | onBadgeUnlocked | { badgeCode, badgeName? } |
reward:claimed | reward | onRewardClaimed | { rewardName, rewardType, codeValue? } |
engagement:resize | internal | internal | { height } (auto-height plumbing) |
engagement:completed (script-tag alias complete, React prop onComplete) is wired on the consumer side but the runtime does not currently emit it. Do not build a flow that depends on it; derive completion from activity:completed events or read state server-side. This note will be removed if/when the emitter ships. Separately, onEligibilityCheck IS live: it fires with the eligibility result when you pass checkEligibility to BricqsEngagement (it is driven by the eligibility API, not by a postMessage event).Script tag: window.Bricqs
The embed script exposes window.Bricqs (capital B) with .on(event, handler) and .off(event, handler). It accepts the SHORT alias names from the table above, not the colon postMessage types.
Bricqs.on('points', ({ points, newBalance }) => {
toast('+' + points + ' points, balance ' + newBalance);
});
Bricqs.on('badge', ({ badgeCode, badgeName }) => {
toast('Badge unlocked: ' + (badgeName || badgeCode));
});
Bricqs.on('activity:complete', ({ activityType, actionResults }) => {
analytics.track('bricqs_activity_completed', { activityType });
});
Bricqs.on('reward', ({ rewardName, codeValue }) => {
if (codeValue) showCouponModal(rewardName, codeValue);
});
Bricqs.on('tier', ({ tierName, tierLevel }) => {
toast('Welcome to ' + tierName);
});Raw iframe: postMessage listener
window.addEventListener('message', (event) => {
const data = event.data;
if (!data || data.source !== 'bricqs') return;
switch (data.type) {
case 'points:awarded':
updatePointsWidget(data.payload.newBalance);
break;
case 'badge:unlocked':
celebrate(data.payload.badgeCode);
break;
case 'activity:completed':
analytics.track('bricqs_activity', data.payload);
break;
}
});Messages are targeted at your page’s origin. There is no bricqs:<event> concatenated naming scheme; source and type are separate fields.
React SDK: callback props
import { BricqsEngagement } from '@bricqs/sdk-react';
<BricqsEngagement
id="YOUR_ENGAGEMENT_UUID"
onReady={() => setLoaded(true)} // onReady receives no arguments
onActivityComplete={({ activityType, actionResults }) =>
analytics.track('bricqs_activity_completed', { activityType })}
onPointsAwarded={({ points, newBalance }) =>
toast(`+${points} points`)}
onBadgeUnlocked={({ badgeCode, badgeName }) =>
toast(`Badge: ${badgeName ?? badgeCode}`)}
onTierChanged={({ tierName }) => confettiFor(tierName)}
onRewardClaimed={({ rewardName, codeValue }) =>
codeValue && showCouponModal(rewardName, codeValue)}
/>Headless hooks do not use this surface at all: they fetch and refresh data directly, and live server events arrive via useBricqsStream (see the Headless SDK pages).
