Navigation

Webpage Survey Invite Blocks

Both GrapesJS editors offer the owner's published surveys as drag-in invite-button blocks — the email editor for a send (email personalization), the webpage editor for a landing page that collects responses from anyone who finds it, with zero send infrastructure.

How it works

The two editors differ in exactly one thing: their canvas markup. Email is MJML, webpage is plain HTML. So the block-building code is a shared core producing the survey list, block identity and public URL, plus a thin per-editor wrapper supplying only its button renderer — one primitive with two flavours, never a copy.

flowchart LR
  SURVEYS["useReadPublishedSurveys<br/>owner's published surveys"] --> CORE["createSurveyInviteBlocks<br/>shared core — list, ids, public urls"]
  CORE -->|"createEmailSurveyInviteBlocks<br/>mj-button markup"| EMAILBM["email block manager"]
  CORE -->|"createWebpageSurveyInviteBlocks<br/>self-styled anchor markup"| WEBBM["webpage block manager"]
  EMAILBM -->|setBlocks re-sync| EMAILCANVAS["email canvas"]
  WEBBM -->|setBlocks re-sync| CANVAS["webpage canvas"]
  CANVAS -->|publish| VIEW["/view/Webpage/[id]<br/>public page with live survey links"]
  • Block source — useReadPublishedSurveys reads the owner's surveys and keeps only the published ones: a draft survey has no public URL for a block to link. Both editors share it.
  • Block content — a styled button linking RoutePath.View(ResourceType.Survey, id). The webpage flavour carries its own inline styling, since a published page loads no stylesheet of ours. Survey names are HTML-escaped into both the block label and the button markup.
  • Re-sync — the block category is replaced wholesale through setBlocks whenever the editor or the survey list changes, so no per-block bookkeeping is needed. The watch itself is shared too (useSurveyInviteBlocks): each editor hands it the live editor, the survey list and its own renderer, and owns none of the wiring.
  • No per-recipient identity — there is no audience row behind an anonymous page visitor, so a webpage block is always the plain published URL. Invite tokens belong to a distribution orchestrator, not a public page.

Key files

FileRole
apps/web/app/services/grapesjs/createSurveyInviteBlocks.tsshared core — survey list to block defs
apps/web/app/services/emailEditor/createEmailSurveyInviteBlocks.tsMJML button flavour
apps/web/app/services/webpageEditor/createWebpageSurveyInviteBlocks.tsplain-HTML button flavour
apps/web/app/composables/survey/useReadPublishedSurveys.tsthe shared block source
apps/web/app/composables/grapesjs/useSurveyInviteBlocks.tsthe shared re-sync watch both editors call
apps/web/app/services/grapesjs/setBlocks.tswholesale block-category re-sync

Notes

  • Embedding a survey inline (an iframe of the respondent page) is deliberately out: iframes inside GrapesJS canvases and published pages bring sizing and sandboxing complexity for marginal gain over a button, and the respondent page is already mobile-friendly. Revisit only on real demand.
  • The full list-to-blocks behaviour is tested once against the shared core; each wrapper test asserts only its own markup flavour.

Details

Command palette

Keyboard shortcuts