Topics & the preference center
Let contacts choose which kinds of email they receive — per topic and per channel — with a hosted, per-topic preference center, double opt-in, and a full consent history
A single "subscribed / unsubscribed" switch is too blunt once you send more than one kind of email. Topics let a contact keep your security alerts and weekly digest while opting out of promotions — instead of unsubscribing from everything. This guide covers creating topics, the hosted preference center, double opt-in, and the consent history.
Topics
A topic is a kind of communication a contact can subscribe to independently — Product updates, Security alerts, Weekly digest, Promotions, Billing notifications, and so on. Create and manage them in Settings › Data › Topics.
Each topic has:
| Field | What it does |
|---|---|
| Name | What the contact sees in the preference center (e.g. "Weekly digest"). |
| Key | A stable machine identifier (e.g. weekly_digest) — the contract for the API and imports. Immutable once created. |
| Channels | Which channels the topic is offered on (email, SMS). Defaults to email. |
| Required | Transactional-class topics (security, billing). Shown locked in the center and always delivered, even to a contact who turned off all marketing. |
| Subscribed by default | Whether a brand-new contact counts as subscribed to this optional topic until they say otherwise. |
| Double opt-in | Requires the contact to confirm via an emailed link before the opt-in counts (see below). |
Topics are presentation and consent only — they never change how an event is produced or how a workflow matches. A project with no topics behaves exactly as before.
Required vs optional
- Required topics bypass the master switch. They're for mail a contact can't reasonably opt out of — a security alert, a billing notice. The preference center shows them as Always on.
- Optional topics need both the channel master on and a topic-level opt-in. This is the normal case.
The hosted preference center
Every marketing (and headless) email already carries a personalized link to a hosted page — you don't build or host anything. With topics defined, that page becomes a per-topic, per-channel center:
- A master switch for marketing email.
- One toggle per optional topic.
- Required topics shown locked ("Always on").
- An "unsubscribe from everything" escape hatch (the one-click target for the
List-Unsubscribeheader).
The page is reached through a signed token — no contact id in the URL — and is rendered in the contact's language. Links already sitting in old inboxes keep working.
Attaching a topic to a campaign
When you set a campaign's topic, its audience is automatically narrowed to the contacts opted in to that topic. A campaign with no topic keeps today's behaviour (everyone subscribed to marketing).
Double opt-in
Turn on Double opt-in for a topic and an opt-in no longer counts until the contact confirms:
- The contact opts in (via the preference center or a form). Their state becomes pending — they receive no topic mail yet.
- Bitelio emails a confirmation link from your verified sending domain.
- Clicking it flips them to subscribed and stamps the active consent version (what they agreed to, and when).
A pending contact never receives the topic's mail, so an unconfirmed opt-in can never leak into a send.
Consent history
Every consent change — a toggle in the center, a form submission, a bounce, a complaint, an import — is written to an append-only consent history. Open a contact and select the Consent tab to read it: what changed, when, the source, and the reason. This is the record you reach for during a compliance review.
Building your own preference center
You don't have to use the hosted page. Mint a link for a contact and either embed it or drive the public API yourself:
# Generate a preference-center link for a contact (authenticated, secret key)
POST /contacts/{id}/preference-link
→ { "token": "v1.…", "url": "https://app.…/preferences/v1.…" }Then read and write preferences against the token — no auth, the token is the capability:
GET /preferences/{token} # current state: channel master + topics
PUT /preferences/{token} # { topics: { weekly_digest: { email: true } }, channelMaster: { email: true } }
POST /preferences/{token}/unsubscribe-allOpting a contact into a double opt-in topic through the API triggers the same confirmation flow.
Related
- Unsubscribe & preferences pages — the link variables injected into every send.
- Email suppressions — the do-not-send list.
- Importing consent — bring topic consent from another platform.