Muin is in private beta.Watch the public release announcement —talk to us.
Falaah Falaah AI

Embedding Muin on Your Site

Drop a Muin smart form, donation page, giving page, or kiosk into any third-party site with a single iframe tag — no SDK, API key, or CORS setup.

Any Muin public surface under /go/* or /embed/* can be iframe-embedded on a third-party site with a single <iframe> tag. There is no SDK, no API key, and no CORS preflight to configure — the response headers do the work.

What you can embed

SurfacePath shapeExamples
Smart forms/go/<tenant>/form/<slug>Volunteer signup, intake, contact
Donation pages/go/<tenant>/donate/<slug>One-time, sustainer, programs
Giving pages/go/<tenant>/giveCampaign hubs
Kiosk/go/<tenant>/kioskTabletop / event sign-in
Embed-only widgets/embed/<tenant>/<widget>Donation block, progress bar

Any other path (admin routes, authenticated dashboards, /api/*) is deliberately blocked from iframe embedding — the response middleware sets X-Frame-Options: DENY and Content-Security-Policy: frame-ancestors 'none' on those.

Quick start: one-line iframe

<iframe
  src="https://muin.falaah.ai/go/your-tenant/donate/sustainer?embedded=true"
  width="100%"
  height="700"
  frameborder="0"
  style="border: none; border-radius: 8px;"
  title="Donate"
></iframe>

That’s the whole integration. The iframe loads cross-origin from muin.falaah.ai and renders the form. Submissions hit Muin directly — your host page doesn’t proxy anything.

Embed shapes

The same /go/* URL works in any of these placements. Live demos at /live/embed-shapes:

  1. Inline iframe — drops into normal page flow at a fixed height.
  2. Side widget — sticky sidebar iframe, scroll-pinned.
  3. Modal — click a button, <dialog> opens with the iframe inside.
  4. Scroll-popup — iframe surfaces after the visitor scrolls past 50%.
  5. Exit-intent — iframe surfaces when the cursor leaves the top edge.
  6. Floating action button — a bottom-right circular button reveals a slide-up panel.
  7. Banner — a top strip with an embedded mini-form, dismissible for 7 days.

You can mix and match — a single page can have a banner, an inline embed, and a FAB simultaneously.

What gets passed through

  • ?embedded=true — appended by embedUrl() as a marker query param. Drives no chrome changes today; it’s a forward-looking hook your host page can also key off (analytics, A/B tests).
  • Other query strings on the URL — preserved end-to-end. Use them to pre-fill fields supported by HiddenField.
  • Iframe-to-parent messages — when a form submits successfully, Muin posts a muin:form-submitted MessageEvent to window.parent so your host page can react (close the modal, fire confetti, redirect). See transitions.

What does NOT work in an embed

BehaviorWhy
Browser auth / login flowsEmbedded forms run anonymously; no auth needed
Cookies (third-party blocked)Forms don’t rely on cookies; tokens go in body
Top-level navigation from iframeSandboxed by browsers; trigger via postMessage
Forms behind tenant authorizationUse the standalone URL, not embed

Building URLs programmatically

If you’re embedding from another Muin tool (a marketing site, a microsite), use the helpers instead of hardcoding the origin:

import { embedUrl, embedSnippet } from "@/lib/embed";

const url = embedUrl("/go/your-tenant/donate/sustainer");
// → "https://muin.falaah.ai/go/your-tenant/donate/sustainer?embedded=true"

const html = embedSnippet("/go/your-tenant/form/volunteer", {
  height: 800,
  title: "Volunteer signup",
});
// → "<iframe src='...' width='100%' height='800' ... title='Volunteer signup'></iframe>"

The helpers read PUBLIC_APP_URL from env so your dev / staging / prod URLs stay consistent without code changes.

Live examples

Next