Skip to content
Sections

Guides

Embed a guest widget

Mount an isolated reservation, preorder or table flow with verified parent authority and private native recovery.

Prepare the actual widget connection

Use /venues/:venueId/settings/storefront for a venue, or /organizations/:organizationId/storefront for a brand. Venue setup uses venueSettings; organization setup requires organization.manage. Publish the reviewed presentation, add a WIDGET connection, attach the exact native PREORDER, RESERVATION or QR resource, and register the embedding website as its WIDGET_PARENT binding. Verify the issued DNS challenge and activate only after current readiness permits it.

The responsible operator configures HALLIFY_WIDGET_FRAME_ORIGIN as an isolated origin, separate from account and API cookie hosts. Use that exact frameOrigin and the issued parentBindingId; a parent binding is not a native resource ID. Native reservation, fulfillment, QR and merchant policies are still configured in their owning workspaces. No public widget API creates settings, staff permissions, payment keys or a sandbox.

Mount with public selectors

The SDK module entry is /sdk/0.1.0/browser/index.mjs. The route and source package are prepared by this implementation; this documentation does not confirm that the version has been deployed at the public origin or published to npm. Replace the synthetic frame origin and UUIDs below with values issued for your actual connection before using the snippet.

Choose flow reservation, preorder or table and locale en, ka or ru. widgetId is a stable 1–64 character identifier using letters, digits, underscore or hyphen: keep it across reload and make it unique per integration slot. The SDK generates a separate fresh random message instance for each mount. Only table flow may supply tableLocator when the native table journey needs it. ready resolves when the initialized frame reports ready; destroy is idempotent and removes only this mount’s resources.

Request examples
<div id="hallify-reservation"></div>
<button id="close-widget" type="button">Close</button>
<p id="widget-status" role="status">Loading...</p>
<script type="module">
  import { mountWidget } from 'https://hallify.co/sdk/0.1.0/browser/index.mjs';

  const widget = mountWidget(document.getElementById('hallify-reservation'), {
    frameOrigin: 'https://widgets.example.invalid',
    connectionId: '2604de3a-da74-4ad5-89f6-2dfe000d5391',
    parentBindingId: '3604de3a-da74-4ad5-89f6-2dfe000d5391',
    venueId: '4604de3a-da74-4ad5-89f6-2dfe000d5391',
    flow: 'reservation',
    locale: 'en',
    widgetId: 'reservation-main',
  });

  document.getElementById('close-widget').addEventListener('click', () => {
    widget.destroy();
  });

  try {
    await widget.ready;
    document.getElementById('widget-status').textContent = 'Ready';
  } catch {
    document.getElementById('widget-status').textContent = 'Widget unavailable';
  }
</script>

Keep the frame and parent boundaries exact

The fixed frame path is /widgets/:connectionId with public query selectors binding, venue when selected, flow, lng, widgetId and the fresh instance; table may additionally use locator. No proof or native credential goes in this URL. Bootstrap runs inside the frame at its actual isolated Origin, returns exact parent/frame/API origins and resolves the current typed resource/channel. The parent never receives swc1.

The frame validates its exact parent and waits for a valid hello/init handshake before business work. Message checks require exact origin, source, protocol version, instance and payload shape. ACTIVE bootstrap admits NEW_DEMAND with current publication and short-lived context; DISABLED can return CONTINUATION_ONLY with no new proof or discovery. Retained native capabilities independently govern the original continuation and deadlines.

New widget demand sends its swc1 proof as x-hallify-widget-context inside the frame request boundary. It proves presentation, not native guest ownership. Existing draft/manage/membership/payment credentials remain separate. Proof renewal does not renew a draft, quote, grant, payment window or original command. The browser supplies Origin; never substitute the embedding parent or use account cookies.

Use safe events and independent storage slots

Public events are ready, bounded resize, close-requested, flow-completed and error with an allowlisted code. They carry no business/private IDs, contact data, verification code, capability or provider payload. flow-completed reports a flow milestone and is not payment, final confirmation or settlement proof. Read the owning native state for those facts.

Native private storage, cache and command journals are scoped by verified parent binding, connection, venue/flow and stable widgetId. Two same-origin frames need different stable slots; reloading the same slot can recover its original command. The random message instance supplies freshness for the current mount and never replaces this recovery key. Neither selector grants authority. Unmounting does not cancel committed orders, bookings or payments.

Move payment to its saved top-level receiver

Use native QR_MEMBERSHIP, PREORDER_MANAGE or RESERVATION_MANAGE payment admission inside the widget. Before prepare-transition, save one transition UUID and a cryptographically random gpw1_ permit, then send only its SHA-256 digest with the current private payment access. The reply freezes destinationOrigin and expiresAt for at most sixty seconds within original authority; it creates no consent, financial command or provider operation.

The private fixed-destination top-level form POST carries only the permit and transition UUID, never native/payment-access credentials, a parent relay or an opener dependency. The canonical receiver saves its own capability/handoff tuple before claim-transition, repeats the exact tuple after uncertainty, then uses ordinary redeem-handoff and the original checkout/journal. Losing that tuple does not permit a replacement receiver, command or charge. UNKNOWN remains unresolved.

Separate source delivery from live qualification

Native booking/ordering/table, guarantee consent and recovery rules remain authoritative. Preorder ordering can use the native configured SELF, UBER_DIRECT or WOLT_DRIVE delivery choices and customer quote recovery described in the Public preorders guide. The accepted customer delivery fee is separate from a later staff carrier dispatch cost; courier state does not prove meal payment or refund. Wolt Drive needs real dropoff coordinates, and the frame does not invent them. Staff courier commands and provider credentials stay outside the widget and its safe parent events. Settings, DNS/TLS, actual frame deployment, third-party storage behavior, browser journeys and Stripe/BOG/TBC or carrier live qualification require their real environment. Source implementation, generated types and safe event examples do not establish those long/live results or npm publication.

Hallify uses essential cookies and optional analytics.

Essential cookies keep sign-in, locale, and theme preferences working. Analytics is off until you choose to allow it.