BitelioBitelio

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:

FieldWhat it does
NameWhat the contact sees in the preference center (e.g. "Weekly digest").
KeyA stable machine identifier (e.g. weekly_digest) — the contract for the API and imports. Immutable once created.
ChannelsWhich channels the topic is offered on (email, SMS). Defaults to email.
RequiredTransactional-class topics (security, billing). Shown locked in the center and always delivered, even to a contact who turned off all marketing.
Subscribed by defaultWhether a brand-new contact counts as subscribed to this optional topic until they say otherwise.
Double opt-inRequires 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-Unsubscribe header).

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:

  1. The contact opts in (via the preference center or a form). Their state becomes pending — they receive no topic mail yet.
  2. Bitelio emails a confirmation link from your verified sending domain.
  3. 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.

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-all

Opting a contact into a double opt-in topic through the API triggers the same confirmation flow.