Skip to content

PRD 15 — Integrations & Embed Widget

Status: draft · Priority tier: P2 · Size: M · Depends on: PRD 01 (business, locations), storefront/online store PRD, services and pricing-plan PRDs (widget content), notifications PRD (email sender)

1. Summary

Two things: (1) an embed widget generator so a studio can put its timetable and catalogs on any website via a copy-paste snippet, with look-and-feel and display options across six tabs; (2) an integrations hub listing email provider, SMS/WhatsApp, class-marketplace aggregator and smart-lock cards, plus storefront tracking-pixel preferences. Third-party items are official-API-only and mostly Later.

2. Problem & goals

Problem: studios already have a website and want bookings from it; they also want analytics on their store traffic. Goals:

  • A non-technical owner generates and copies a working snippet in ≤4 clicks plus option changes.
  • Snippet renders on a plain HTML page and on a page-builder embed with no extra code.
  • UTM parameters from the host page reach the booking flow (attribution intact).
  • Tracking IDs saved once and injected on the storefront within one publish cycle. Non-goals: building any third-party connector in v1; WYSIWYG site builder; custom CSS injection.

3. Users & roles

Owner/manager (Settings > Embed widget / Integrations / Online store preferences edit); marketer (preferences); website visitor (sees the widget); customer (books through it).

4. Scope

In (v1)

  • must: Embed widget with 6 tabs (timetable, class list, appointment list, course list, membership list, package list), options, preview, snippet copy.
  • must: Look-and-feel options (font, six colours) shared across tabs.
  • should: UTM passthrough from host page to widget; open-in-new-tab / hide-branding options.
  • should: Tracking preferences: Meta pixel, GA4, Google Tag Manager, TikTok pixel IDs, Meta and Google site-verification tokens.
  • should: Integrations hub page with category cards and connection state (connected / not connected).
  • should: Built-in email provider card (our own sending; connection state, sender verification status read from notifications PRD). Later (v2+)

  • SMS/WhatsApp provider connection (e.g. a CPaaS via its public API) (pricing tier: TBD).

  • Smart-lock connection via the vendor's public API for PIN/bluetooth entry (links to PRD 10).
  • Per-widget GA ID override; widget analytics.
  • Customer-consent banner gating pixels. Out

  • Class-marketplace aggregator (ClassPass-like): no public partner API was observed; the original's flow is "Book a demo". Show a "request" card at most; no booking sync. Reason: contractual/partner-only, cannot be cloned.

  • Copying the original's widget host, script, class names or branding.

5. User stories

  • US-15-01 As an owner, I want to choose a widget type and options, so that my site shows the right thing.
  • US-15-02 As an owner, I want to match the widget's colours and font to my site, so that it looks native.
  • US-15-03 As an owner, I want to copy a snippet, so that I can paste it into my site without a developer.
  • US-15-04 As a marketer, I want campaign UTM tags on my site to follow the visitor into booking, so that sales are attributed.
  • US-15-05 As a marketer, I want to paste my pixel and analytics IDs once, so that the storefront reports to them.
  • US-15-06 As an owner, I want to see which integrations are connected, so that I know what is active.
  • US-15-07 As an owner, I want to be told which integrations are coming, so that I can plan.

6. Functional requirements

ID requirement priority evidence
FR-15-01 Embed page with 6 tabs; selected tab in URL hash; options per tab; live preview; Copy button with confirmation must S158, F58
FR-15-02 Timetable tab: show classes / appointments checkboxes (at least one), default layout list or grid, show slots left, class category and location filters, appointment category and location filters must S158
FR-15-03 Location filters appear only if the business has more than one location should S158
FR-15-04 Class list and appointment list tabs: show ratings option should S158b, S158c
FR-15-05 Course list tab: show ratings, show price should S158d
FR-15-06 Membership list tab: category filter, show price should S158e
FR-15-07 Package list tab: category filter, show price should S158f
FR-15-08 Look and feel: font choice, primary and secondary background, text, solid-button text and background, outlined-button and text colours (hex validated); shared across tabs must S158
FR-15-09 Advanced: optional analytics tracking ID applied inside the widget could S158
FR-15-10 Output: an iframe snippet whose URL carries the business ID and all options as query params; options encoded, no secrets must S158
FR-15-11 Optional helper script forwards the host page's UTM params into the iframe via postMessage; widget validates message origin should S158
FR-15-12 Options: open booking in new tab, hide our branding (branding hide may be plan-gated, pricing tier: TBD) should S158
FR-15-13 Widget shows only published, public, upcoming items; private items never exposed must 08 gapfill storefront note
FR-15-14 Widget endpoint is public, read-only, rate limited; booking/checkout continues on the storefront with login must security; F58
FR-15-15 Allowed-origins setting (optional) to restrict which sites may frame the widget could our addition
FR-15-16 Integrations hub with categories (Marketing, Booking, Hardware); each card: name, short description, state, action should S157
FR-15-17 Email card: built-in sending; show monthly allowance/usage if our plan has one (pricing tier: TBD) should S157b
FR-15-18 SMS/WhatsApp card: marked "coming later" in v1; if built, credentials stored encrypted server-side, never shown after save could S157b
FR-15-19 Booking-marketplace card: not built (Out); no toggle could S157c
FR-15-20 Smart-lock card: "coming later", official vendor API only; links to PRD 10 could S157d
FR-15-21 Tracking preferences form: Meta pixel ID, GA4 ID (G-...), GTM ID (GTM-...), TikTok pixel ID; format validation; one Save, disabled until changed should S115
FR-15-22 Site verification: Meta domain verification token and Google verification token rendered as meta tags on the storefront should S115
FR-15-23 IDs injected on the storefront only after publish; empty value removes the script should features.csv
FR-15-24 Settings and integration pages respect permissions (section 11) must permission matrix

7. Screens

  • Embed widget (S158 and variants b-f): tabs, options panel, colour inputs, snippet box with Copy. States: loading, no-locations hint, filled, copy-success.
  • Integrations hub (S157), marketing (S157b), booking (S157c), hardware (S157d).
  • Online store preferences (S115): empty, filled, validation error, saved toast. Our version shows a live preview next to the options (the original showed options + snippet; preview was not confirmed).

8. Flows

Embed: Settings > Embed widget > tab > set options > Copy (original: choose tab, set options, copy; target ≤4 clicks excluding options). Pixels: Online store > Preferences > paste IDs > Save. Integrations: hub > card > connect or "coming later" detail. Edge cases: invalid hex; no published items (preview empty state with link); deleted category in filter (ignored); host page blocks iframes (doc hint); duplicate pixel installed by site and storefront (hint).

9. Data model

  • EmbedWidgetConfig (optional save): business_id, type, options JSON, colours, font, ga_id, allowed_origins (guess: snippet is stateless, so storing config may be unnecessary).
  • Integration: business_id, provider key (email_builtin, sms, aggregator, smart_lock), state, config (encrypted), connected_at.
  • TrackingPrefs: business_id, meta_pixel_id, ga4_id, gtm_id, tiktok_pixel_id, meta_domain_verification, google_site_verification.

10. Business rules & edge cases

  • Widget parameters are validated server-side; unknown params ignored.
  • Colours stored as 6-digit hex; font from a fixed list.
  • Third-party credentials: official APIs/OAuth only, secrets never logged or returned.
  • Pixel and analytics firing may require customer consent (jurisdiction); defer consent banner to Later and warn the owner.
  • Widget must work when cookies are blocked (guest browse); login happens on the storefront.

11. Permissions

  • Settings > Embed widget: view = see page, edit = same (generate only); no data is modified.
  • Settings > Integrations: edit to connect/disconnect.
  • Online store > Preferences: edit to change pixels.
  • Owner/Admin: all.

12. Acceptance criteria

  • AC-01: Given 2 locations, when I open the timetable tab, then location filters are shown; with 1 location they are hidden.
  • AC-02: Given options changed, when I press Copy, then the clipboard contains a snippet whose URL includes those options and a "copied" confirmation shows.
  • AC-03: Given the snippet pasted in a static page, then the widget lists only published upcoming sessions.
  • AC-04: Given host URL has utm_source=x, when the helper script runs, then the widget's booking links carry utm_source=x.
  • AC-05: Given a private class, then it never appears in any widget response.
  • AC-06: Given GA ID "abc", then Save is blocked with a format error; given "G-ABC123", saved.
  • AC-07: Given saved GTM ID, when the storefront loads, then the GTM script with that ID is present; after clearing it, absent.
  • AC-08: Given the aggregator card, then no connect toggle exists.

13. Dependencies & open questions

Depends on PRD 01, storefront, services, pricing plans. Open:

  • Pixel injection behaviour on the storefront was not observed (only the form); assumed standard script tags.
  • Whether widget config is saved server-side in the original is unknown (not observed).
  • Exact widget font list: only the default (a sans font) was seen.
  • Are ratings available (reviews module exists in our roadmap?).
  • Branding-hide gating and email allowance (pricing tier: TBD).
  • Whether to ship an SMS provider in v1 (needs a provider decision).
  • Cookie consent requirements per target market.

14. Evidence

See evidence/evidence.md.