SayWall
Documentation

Embedding a Form

Add a SayWall collection form to any website — inline in your page, as a centered popup, or as a floating corner widget.

Updated March 12, 2026

Quick Start

Get a collection form on your page in under 5 minutes.

1
Open the Embed tab

In the SayWall dashboard, go to Forms, open your form, and click the Share tab. Choose your display mode (Inline, Popup, or Floating), configure any options, then copy the embed snippet.

2
Paste into your HTML

Paste the snippet into your page's HTML. The <script> tag needs to appear only once per page (before </body>). The <div> goes wherever you want the form to render (inline mode) or anywhere on the page (popup and floating modes).

<div data-saywall-collect="YOUR_FORM_ID"></div>
<script src="https://saywall.io/collect-embed.min.js" async></script>
3
See the form appear

Save and reload your page. The script loads asynchronously and won't block your page render. For inline mode the form appears in place. For popup and floating modes, the configured trigger fires automatically.

Display Modes

Pro feature: Inline, popup, and floating embed modes require a Pro plan. The public form page is available on all plans.

SayWall collection forms support three display modes. You choose the mode in the Share tab of the form editor — the embed snippet is generated automatically to match your settings.

ModeHow it appearsBest for
InlineRendered directly in your page contentDedicated feedback pages, landing pages
PopupCentered modal overlay with a backdropPost-purchase flows, capturing attention
FloatingCorner widget that floats over your pageNon-intrusive, persistent collection

Inline Mode

The default. The form renders in the exact position of the <div>.

<div data-saywall-collect="YOUR_FORM_ID"></div>
<script src="https://saywall.io/collect-embed.min.js" async></script>

The <div> can be placed anywhere — it is invisible. The form opens as a modal overlay based on your trigger settings.

<div
  data-saywall-collect="YOUR_FORM_ID"
  data-mode="popup"
  data-trigger="button"
  data-trigger-text="Leave a Review"
  data-trigger-position="bottom-right"
  data-trigger-color="#4f46e5"
  data-trigger-text-color="#ffffff"
  data-popup-size="md"
></div>
<script src="https://saywall.io/collect-embed.min.js" async></script>

Floating Mode

The form appears as a floating card anchored to a corner of the viewport.

<div
  data-saywall-collect="YOUR_FORM_ID"
  data-mode="slidein"
  data-trigger="button"
  data-trigger-text="Leave a Review"
  data-trigger-position="bottom-right"
  data-slidein-position="bottom-right"
></div>
<script src="https://saywall.io/collect-embed.min.js" async></script>

HTML vs React/Next.js

<!-- Place the div where you want the form (inline) or anywhere (popup/floating) -->
<div data-saywall-collect="YOUR_FORM_ID"></div>
 
<!-- Place the script once per page, before </body> -->
<script src="https://saywall.io/collect-embed.min.js" async></script>

Trigger Types

Popup and floating forms fire based on a trigger. You configure the trigger in the dashboard — the attribute is included in the generated embed code automatically.

data-trigger valueBehaviour
buttonRenders a fixed floating button. Clicking it opens the form.
delayOpens the form automatically after N seconds. Once per session.
exit_intentOpens when the user moves their cursor toward the browser close/back button. Desktop only. Once per session.
api_onlyNo automatic trigger. Open and close the form with the JS API.

delay and exit_intent triggers fire once per browser session using sessionStorage. If the user closes the form and revisits the page in the same session, it will not reappear automatically.

Exit intent is desktop-only. Mobile browsers do not expose the cursor position needed to detect exit intent. If mobile coverage matters, use button or delay instead.

Data Attributes Reference

Core attributes

AttributeRequiredDescription
data-saywall-collectYesYour form's short ID (copied from the dashboard)
data-modeNoinline (default), popup, or slidein

Trigger attributes (popup and floating modes)

AttributeDefaultDescription
data-triggerbuttonTrigger type: button, delay, exit_intent, or api_only
data-trigger-text"Leave a Review"Label on the floating trigger button
data-trigger-positionbottom-rightButton position: bottom-right, bottom-left, or bottom-center
data-trigger-color#4f46e5Button background color (hex)
data-trigger-text-color#ffffffButton label color (hex)
data-trigger-delay5Seconds before auto-open (only for data-trigger="delay")
AttributeDefaultDescription
data-popup-sizemdDialog width: sm (480 px max), md (560 px max), or lg (640 px max)
data-popup-close-backdroptrueSet to "false" to prevent closing by clicking the backdrop
data-popup-close-esctrueSet to "false" to prevent closing with the Escape key

Floating-specific attributes

AttributeDefaultDescription
data-slidein-positionbottom-rightCorner position: bottom-right or bottom-left

JS API

For popup and floating forms you can open and close the form from your own JavaScript — useful when you want to trigger collection after a user action (e.g., completing a purchase).

// Open the form
SayWall.open("YOUR_FORM_ID", { mode: "popup" });
 
// Close the form
SayWall.close("YOUR_FORM_ID");

SayWall.open() accepts an optional options object:

OptionDefaultDescription
mode"popup""popup" or "slidein"
popupSize"md""sm", "md", or "lg"
closeOnBackdroptrueAllow closing by clicking the backdrop
closeOnEsctrueAllow closing with the Escape key
slideinPosition"bottom-right""bottom-right" or "bottom-left"

To use the JS API without any automatic trigger, set data-trigger="api_only" on the embed div. No floating button will be rendered — the form opens only when your code calls SayWall.open().

You cannot call SayWall.open() with a form ID that is already embedded as an inline form on the same page. The script will log a warning and do nothing. Use a separate form ID for inline vs overlay embeds.

How It Works

The embed script uses Shadow DOM to render the form in isolation from your page.

When collect-embed.min.js initialises:

  1. It scans the page for any data-saywall-collect elements (including ones added dynamically after load)
  2. For inline mode it fetches and renders the form immediately in place
  3. For popup / floating mode it sets up the configured trigger, then fetches the form when it's about to open
  4. It attaches a shadow root to the host element and injects the form styles and HTML inside it

The shadow root completely isolates the form's styles from your page — no CSS conflicts in either direction.

CSP Requirements

The collection form embed requires script-src 'unsafe-eval' in your Content Security Policy.

Add this to your Content-Security-Policy header:

script-src 'self' https://saywall.io 'unsafe-eval';

If reCAPTCHA spam protection is enabled on your form, also allow:

script-src 'self' https://saywall.io https://www.google.com/recaptcha/ https://www.gstatic.com/ 'unsafe-eval';

Every collection form also has a standalone URL:

https://saywall.io/t/YOUR_PROJECT_SLUG/YOUR_FORM_SLUG

You can share this link directly in emails, QR codes, or social posts — no embed required. The link is shown in the Share tab of the form editor alongside the embed code.

Frequently Asked Questions

Start collecting testimonials for free

Set up in minutes. No credit card required.

Get started free

Need help?

Have a question or need assistance? Reach us at hello@saywall.io