(list, email), and an address can sit on several lists. What the owner sees is in Guides: Signups.
The pieces
Declaring a list
The list is a prop on the component. Lowercase slug, letters, digits,- and _, up to 40 characters.
Extra details
Any input namedfields.<key> is sent alongside the email and stored on the row under that key. They become columns in the CSV export and a column on the card.
fields into the existing row. That is how a two-step signup works: email first, then a follow-up question whose answer is posted as fields.<key>.
The request
If you build your own markup instead of the template’s component, this is the contract. The component readswindow.__apiUrl and window.__siteDomain, which the base layout already sets for the contact overlay. It fetches a token from /api/form-token when the visitor first focuses the form and waits until the token is at least two seconds old before posting: the API rejects younger tokens, so a token fetched at submit time and spent at once always fails.
The same checks as the contact form apply: syntax, a disposable-domain blocklist, and a live mail-server lookup. A honeypot field (
_hp) that arrives filled is accepted and discarded.
As a conversion
The first signup to a list emits a custom event keyedsignup:<list>. It appears in the funnel wizard and the A/B goal picker under Custom event, so a list can be a funnel’s last step or a test’s goal with no further wiring. Merges do not emit again.
Database
migrations/signups.sql, additive. Columns: list, email, fields (JSON), source (the page path), status (active / unsubscribed), consent_at, unsubscribed_at, the last-touch attribution columns shared with persons and form_submissions, first_touch. Unique on (org_id, list, email). The function signup_lists(p_org_id) returns each list with its total and active counts; the card opens with it, so the counts always cover the whole list. The table pages through the list ten rows at a time, and an export reads the list’s active members fresh when a format is picked. Exports are limited to the latest 50,000 rows: past that, the file holds the latest 50,000 and its name says so.
Deferred: double opt-in, a public unsubscribe link, deleting from the card.