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.
