Reference

Data attributes

Every HTML attribute Memberflow's CDN script reads on your published Webflow site. Tag elements in the Designer, publish, and the script wires everything up at page load — no JavaScript on your side.

Every attribute shares the data-memberflow- prefix. This namespace is fixed — your pasted Webflow markup depends on it — so it stays the same regardless of branding.

Forms

Mark an element as a Memberflow form. The CDN script intercepts submits and routes to the right API.

data-memberflow-form="login"

Email + password sign-in form.

data-memberflow-form="signup"

Create-account form. Optionally include a tierId input or arrive at this page with ?tier=<id> to pre-pick a tier.

data-memberflow-form="reset-password"

Form that requests a reset email.

data-memberflow-form="reset-password-confirm"

Form that sets a new password using the token from the email link.

data-memberflow-form="profile"

Update first/last name, email, or password for the signed-in member.

data-memberflow-form="delete-account"

Confirm-with-password form that deletes the member account.

Form inputs

Inside any form above, tag each input with which field it carries. Custom field keys (defined in the dashboard's Custom fields section) work here too.

data-memberflow-input="email"

Email input on login / signup / reset / profile forms.

data-memberflow-input="password"

Password input on login / signup / reset-password-confirm.

data-memberflow-input="firstName"

Optional on signup and profile.

data-memberflow-input="lastName"

Optional on signup and profile.

data-memberflow-input="currentPassword"

Required on profile (when changing password) and delete-account.

data-memberflow-input="newPassword"

Required on profile when changing password and on reset-password-confirm.

data-memberflow-input="tierId"

Optional hidden input on signup to lock the new member to a specific tier. Honored only if the tier belongs to this site.

data-memberflow-input="<custom-field-key>"

Any custom field you defined in Dashboard → Custom fields (e.g. company, linkedinUrl). Values are saved on the Member row.

Form feedback

Slots inside a form where the script writes status messages and overrides redirects.

data-memberflow-error

On any element inside a form. Filled with the server's error message; cleared on next submit.

data-memberflow-success

On any element inside a form. Shown when the action succeeds (e.g. reset email sent, profile saved).

data-memberflow-redirect="/some/path"

On the <form> element. Overrides the default post-action redirect (Site Settings → Post-login redirect URL).

data-memberflow-confirm="Are you sure?"

On a delete-account form. Native window.confirm() runs with this text before the request fires.

Action buttons

Stand-alone buttons that trigger member actions without a form.

data-memberflow-action="profile-link"

On the navbar's Profile link. The href is rewritten to the profile page set in Settings, so a pasted navbar keeps working when the profile page is not at the template's suggested slug.

data-memberflow-action="logout"

On a button or link. Clears the member session and reloads.

data-memberflow-action="google-login"

Starts Google sign-in. On a signup page (or with google-signup / data-memberflow-intent="signup") this creates a member if none exists. On a login page the member must already exist. An email/password account with no social provider yet is linked. An email already used with GitHub or Facebook is rejected. Pair with data-memberflow-redirect for the return path.

data-memberflow-action="github-login"

Starts GitHub sign-in. Same login vs signup rules as google-login. An email/password account with no social provider yet is linked. An email already used with Google or Facebook is rejected.

data-memberflow-action="facebook-login"

Starts Facebook sign-in. Same login vs signup rules as google-login. An email/password account with no social provider yet is linked. An email already used with Google, GitHub, Apple, or X is rejected.

data-memberflow-action="apple-login"

Starts Sign in with Apple. Same login vs signup rules as google-login. An email/password account with no social provider yet is linked. An email already used with another social provider is rejected. Later Apple visits may omit email; existing members are matched by Apple id.

data-memberflow-action="twitter-login"

Starts X sign-in. Same login vs signup rules as google-login. The X account must share an email. An email/password account with no social provider yet is linked. An email already used with another social provider is rejected.

data-memberflow-action="discord-login"

Starts Discord sign-in. Same login vs signup rules as google-login. Later Discord visits may omit email; existing members are matched by Discord id. An email/password account with no social provider yet is linked. An email already used with another social provider is rejected.

data-memberflow-action="linkedin-login"

Starts LinkedIn sign-in. Same login vs signup rules as google-login. The LinkedIn account must share an email. An email/password account with no social provider yet is linked. An email already used with another social provider is rejected.

data-memberflow-action="microsoft-login"

Starts Microsoft sign-in. Same login vs signup rules as google-login. Later Microsoft visits may omit email; existing members are matched by Microsoft id. An email/password account with no social provider yet is linked. An email already used with another social provider is rejected.

data-memberflow-action="google-signup | github-signup | facebook-signup | apple-signup | twitter-signup | discord-signup | linkedin-signup | microsoft-signup"

Same as the matching *-login action, but always creates an account when none exists (even if the button is not on the signup page).

data-memberflow-intent="login | signup"

On a social button. Forces login-only or create-if-missing regardless of which page the button is on.

data-memberflow-action="dialog-open"

Opens the named popup on this page. Pair with data-memberflow-dialog="login" (or signup, profile, …). If that overlay is missing, the link's href is used instead (e.g. /login).

data-memberflow-action="dialog-close"

Closes the nearest (or named) membership dialog. Escape and a click on the overlay also close it.

data-memberflow-action="login-open | signup-open | profile-open"

Direct aliases of dialog-open targeting login, signup, or profile dialogs.

data-memberflow-action="login-close | signup-close | profile-close"

Direct aliases of dialog-close for login, signup, or profile dialogs.

data-memberflow-action="menu-toggle"

Toggles a dropdown. Pair with data-memberflow-menu="<name>" and a panel marked data-memberflow-menu-panel="<name>".

data-memberflow-dialog="login | signup | profile | <name>"

Marks the overlay to open. Alias: data-mf-dialog. Hidden on load when a matching dialog-open control exists; otherwise left visible as a page embed.

data-memberflow-menu="<name>"

On the menu-toggle control. Alias: data-mf-menu.

data-memberflow-menu-panel="<name>"

The dropdown panel that menu-toggle shows/hides. Alias: data-mf-menu-panel.

data-memberflow-action="login-open | signup-open | profile-open | login-close | signup-close | profile-close"

Shorthand for dialog-open / dialog-close on the dialog of that name — login-open is the same as dialog-open with dialog="login". Use whichever reads better in the Designer.

data-memberflow-action="upgrade"

On a button or link, paired with data-memberflow-tier. Moves the member onto that paid tier, picking the right path automatically: an existing subscriber changes plan on their current subscription, anyone else goes through Stripe Checkout. Use checkout or switch directly when you want to force one of the two.

data-memberflow-action="checkout"

On a button or link, paired with data-memberflow-tier. Starts a Stripe Checkout subscription for the tier on your connected Stripe account and redirects the visitor to pay. Access is granted automatically once Stripe confirms payment.

data-memberflow-action="switch"

On a button or link, paired with data-memberflow-tier. Moves an existing subscriber to a different paid tier on their current subscription (proration handled by Stripe). For members without a subscription yet, use checkout.

data-memberflow-action="cancel"

On a button or link. Cancels the member's subscription at the end of the current billing period — they keep access until then.

data-memberflow-action="resume"

On a button or link. Undoes a pending cancellation so the subscription renews as normal.

data-memberflow-action="downgrade-free"

On the Free plan's CTA. For a visitor or an already-free member it behaves like the ordinary signup link; for a paying member it cancels the subscription at the end of the period instead, which is otherwise a dead end on the plans page. Confirms first.

data-memberflow-action="undo-switch"

On a button or link, paired with data-memberflow-tier set to the member's CURRENT tier. Cancels a scheduled downgrade so billing carries on unchanged. Shown only on the current plan's card, and only while a change is pending.

data-memberflow-action="billing-portal"

On a button or link. Opens the Stripe Customer Portal where the member can update their card, view invoices, and cancel.

data-memberflow-tier="<tierId>"

Required next to an upgrade, checkout, switch or undo-switch action. The numeric tier id from Dashboard → Tiers.

data-memberflow-plan-summary

Wraps the "your current plan" block above the plans grid. Hidden until the visitor is a member holding a plan. Inside it, data-memberflow-field="tier" / "planPrice" / "currentPeriodEnd" / "cancelAtPeriodEnd" fill themselves in, and the last two are mutually exclusive so the block never contradicts itself.

data-memberflow-plan-status="active | cancelled"

A badge inside the plan summary. Shown when the member's subscription is running, or set to end at the period end. Ships hidden; only the one that applies is revealed.

data-memberflow-plan-pending

The scheduled-change row inside the plan summary. Shown only when a plan change or cancellation is queued for the end of the current period. Put an undo-switch button (for a plan change) and a resume button (for a cancellation) inside it — the script reveals whichever applies and fills in the tier id.

data-memberflow-interval-toggle="monthly | yearly"

On a button or link in the Plans page's billing switch. Clicking it filters the grid to the plans sold on that cadence — free tiers always stay visible — re-prices any tier that sells both, and changes which Stripe price a checkout uses. The selected one gets aria-pressed="true" and an is-active class to style against.

data-memberflow-interval-chrome="plans"

Wraps the billing switch. Hidden automatically unless the paid tiers on the page span more than one cadence — either one tier carrying both prices, or two tiers each sold on one. A switch that changes nothing implies a cheaper option you don't offer.

data-memberflow-interval-only="monthly | yearly"

Shown only while that cadence is selected. For copy belonging to one option, like "2 months free".

data-memberflow-interval-default="yearly"

Opens the page on the yearly cadence instead of monthly. Ignored when no tier offers a yearly price.

data-memberflow-plan-badge="current | scheduled"

On a plan card, paired with data-memberflow-tier. Shown when that tier is the member's current plan, or the plan a scheduled change moves them to. Ships hidden; the script reveals whichever applies and hides the other.

data-memberflow-confirm="<message> | off"

On any of the actions above that changes or ends a subscription (switch, undo-switch, cancel, downgrade-free) or leaves a group. Replaces the confirmation text, or skips the dialog entirely with the literal value "off" when you've built your own confirmation step. Left off, each action uses wording that names the plan, the direction and the date the change takes effect.

Content gating

Show or hide any element based on the signed-in member's status and tier. The CDN script applies these at page-load before paint.

data-memberflow-content="private"

Visible only when a member is signed in.

data-memberflow-content-from="<element id>"

Takes the gate from that element's text instead of a fixed value, so a CMS field can set it per collection item — one blog template can hold a free post, a members-only post and a paid post without duplicating the block. Bind a hidden text element to the field, give it an id, and point this at the id. A static data-memberflow-content on the same element still applies as the default when the field is blank.

data-memberflow-content="!<any mode>"

Inverts the mode that follows. "!level:2" is every visitor who cannot read level-2 content — logged out, or signed in below it — which is exactly the audience for a paywall prompt and previously needed one block per case. An unrecognised mode is never inverted.

data-memberflow-content="level:<n>"

Visible to a member whose PLAN reaches accessLevel n or above — the same ">=" rule page access uses. This is how you say "any paid plan" in one attribute instead of one copy per tier. Groups never count toward it, since a group's level is meaningless.

data-memberflow-content="tier:<id>"

Same as tier:<name> but matched on the numeric tier id from Dashboard → Tiers. Prefer it for anything important: a name match breaks silently the moment the tier is renamed, and it breaks OPEN — the gated element becomes visible to everyone.

data-memberflow-content="public"

Visible only when NO member is signed in.

data-memberflow-content="tier:<name>"

Visible only when the signed-in member's tier name matches (case-insensitive). E.g. tier:Studio Member or tier:vip.

data-memberflow-content="status:<value>"

Visible only when the signed-in member's status matches. Values: active, pending, suspended, cancelled, failed. E.g. status:pending for an 'awaiting approval' notice.

Member field rendering & prefill

Pull data off the signed-in member into the DOM.

data-memberflow-field

On any element. Renders the corresponding member field as text content. Use 'tier' for the tier name; 'status' for a friendly account status ('Active', 'Awaiting approval', …); 'signupProvider' for how they first signed up (Email, Google, GitHub, Facebook, Apple, X, Discord, LinkedIn, Microsoft); 'currentPeriodStart' for the activation date ('Member since ...'); 'currentPeriodEnd' for the renewal/expiry date; 'cancelAtPeriodEnd' for whether a cancel is scheduled. Elements that resolve to nothing are auto-hidden.

data-memberflow-prefill

On an input that already carries data-memberflow-input. Auto-fills the input with the current member's value on page load.

Groups

Joinable, unranked memberships a member holds alongside their plan. A group card needs one element per control; the CDN decides which is visible from the member's state and never creates any of them.

data-memberflow-action="join"

On the card's primary CTA, paired with data-memberflow-tier. Joins the group for a signed-in member. Logged out, the link falls through to /signup?tier=<id> so signing up and joining are one step. Relabels itself Joined or Pending approval and disables once the member is in.

data-memberflow-action="leave-group"

On a link or button in the same card, paired with the tier id. Shown only once the member has joined. Confirms before leaving; add data-memberflow-confirm to change the wording, or set it to "off" to skip.

data-memberflow-action="cancel-request"

Withdraws a pending join request on an approval-gated group. Shown only while a request is outstanding. Ship this alongside leave-group to style and word the two separately; a card with only leave-group keeps serving both states on that one control.

data-memberflow-action="visit-group"

On a link in the card, paired with the tier id. Shown only to members of the group, with its href filled from the page rule that gates the group's page — so the link is never hand-written and a card added later still points at the right group. Stays hidden when no page rule names that tier, or when more than one does.

data-memberflow-action="group-status"

On any element in the card. Shown only while a join request is awaiting approval. Optional — the join control already reads Pending approval in that state.

data-memberflow-tier-members="<tierId>"

On any element. Renders the group's active member count, e.g. "12 members". Pending requests are not counted.

data-memberflow-tier-open="<tierId>"

On any element. Shown only when the group can be joined without approval. Keeps your own wording; fills in Public when left empty.

data-memberflow-tier-approval="<tierId>"

On any element. Shown only when joining the group needs the owner's approval. Keeps your own wording; fills in Private when left empty.

data-memberflow-group-joined="<tierId>"

On any element. Renders the date the viewer joined that group, and hides itself for anyone who has not.

Tier cards

Mark up one card per tier and the CDN keeps it in sync with your dashboard — filling each field, and cloning the card for any tier created after the page was pasted.

data-memberflow-card="<tierId>"

On the card wrapper. Identifies which tier the card belongs to, and is the template the CDN clones for a tier that has no card yet. Elements inside can omit their own tier id.

data-memberflow-plan="<tierId>"

Alternative card marker. A card whose tier no longer exists is hidden rather than left showing stale copy.

data-memberflow-tier-name="<tierId>"

On any element. Renders the tier's name from the dashboard.

data-memberflow-tier-desc="<tierId>"

On any element. Renders the tier's description, and hides itself when the tier has none. Edit the text in Dashboard → Tiers, not in the Designer — it is overwritten on every load.

data-memberflow-empty

On an empty-state block. Shown when the site has no visible tiers of that kind, and hidden again as soon as one exists.

Pricing display

Render live tier prices so a Webflow pricing page stays in sync with your tiers.

data-memberflow-price="<tierId>"

On any element. Renders the tier's price formatted as currency (e.g. $15.00), or 'Free' for free tiers.

data-memberflow-interval="<tierId>"

On any element. Renders the tier's billing interval (monthly / yearly).

Tab / step panels

The CDN shows one sibling panel at a time for library tab layouts. Panels need ids under mf-auth-, mf-pf-, mf-ob-, mf-cs- (content switch), or mf-md- (member desk); tab links use href="#that-id". Shared tab bars also toggle the library active tab classes.

id="mf-auth-signup | mf-auth-login | mf-pf-general | mf-pf-email | mf-pf-password | mf-ob-1 | mf-ob-2 | mf-ob-3 | mf-cs-overview | mf-cs-billing | mf-md-desk | mf-md-rooms | mf-md-billing"

On each panel. Sibling panels with these prefixes hide/show together. The current URL hash picks the visible one; tab links set the hash.

Toasts

Where transient messages appear. Optional — the CDN creates its own container when the page has none.

data-memberflow-toast

On an element you want used as the toast container, so messages inherit your styling and position instead of the default.

Retention offer

Intercepts cancel and shows a stay-and-save modal. The library component uses data-mf-retain; data-memberflow-retain is an equivalent alias. Decline still uses data-memberflow-action="cancel".

data-memberflow-retain

Role on the retention UI. Alias: data-mf-retain. cancel-trigger opens the modal for eligible paid members; accept fires an optional webhook; decline continues with cancel.

data-mf-retain-webhook="https://hook.make.com/…"

On the modal. Optional POST URL (Make.com, Zapier, …) to apply a Stripe coupon. Body includes email, memberId, siteId, coupon.

data-mf-retain-coupon="YOUR_STRIPE_COUPON_ID"

On the modal. Stripe coupon id sent in the webhook payload.

data-mf-retain-max-offers="1"

On the modal. Lifetime max times the offer is shown. Default 1.

data-mf-retain-cooldown="30"

On the modal. Days to wait after a decline before offering again. Default 30.

data-mf-retain-field="retention_offered"

On the modal. Custom-field key used to persist offer history when that field exists in the dashboard. localStorage is always used as a fallback.

Skip the wiring

The dashboard ships pre-wired Webflow Designer clipboard payloads for every form above — login, signup, profile, plans picker, gated elements. Copy → paste → publish.

Try Memberflow