Topics and preferences
What contacts subscribe to, the hosted preference center, one-click unsubscribe and double opt-in.
Topics
A topic is something contacts can subscribe to, like a newsletter or product updates. Its key is
also a category: a broadcast or email with that category is about
the topic.
await ...({
: "newsletter",
: "Newsletter",
: "Monthly product news.",
: "opt_in",
});
await ...("ada@example.com", {
: [{ : "newsletter", : "opted_out" }],
});With default_subscription: "opt_in", every subscribed contact gets the topic's email unless they
opted out; with opt_out, only contacts who opted in do. private topics never show in the
preference center. An environment has at most 100 topics.
The preference center
Every marketing email links to a page coss.com hosts on its tracking domain (or your custom tracking domain), where the recipient sees their public topics, changes their choices or unsubscribes from everything. The links name no address and expire never; opening them changes nothing, only submitting the page does.
Marketing email also carries List-Unsubscribe and List-Unsubscribe-Post headers, so mail clients
show their own unsubscribe button (one click, RFC 8058).
A broadcast's links leave just its topic; others leave marketing email altogether. Unsubscribing
sends a contact.unsubscribed webhook (with topic when it was one topic) and records an
email.unsubscribed event on the email it came from.
A transactional email whose category is a topic's key gets the same headers when it has a single
recipient (and no List-Unsubscribe header of your own). They lead to the preference center rather
than to the per-category one-click unsubscribe: unsubscribing opts the
contact out of the topic instead of adding a suppression.
Put the links in your content with {{{unsubscribe_url}}} and {{{preferences_url}}}, and your
postal address with {{{mailing_address}}}. Without them, coss.com adds a footer with all three.
To link to the page from elsewhere (your app's settings), mint links for a contact:
const { : } = await ...("ada@example.com", {
: "newsletter",
});
// links?.preferences_url, links?.unsubscribe_urlYour postal address
The CAN-SPAM Act requires a valid physical postal address in every commercial email. Set it once in the marketing settings; marketing email can't be sent without one.
await ...({
: "Acme",
: "Acme Inc.\n548 Market St\nSan Francisco, CA 94104, USA",
});Double opt-in
With double opt-in, a new contact stays pending until they click the link in a confirmation email,
which proves they own the address. Turn it on for every contact created through the API
(double_opt_in_default) or per request (double_opt_in); contacts you add or import in the
dashboard, and imports, are added as you set them. Confirmations come from confirmation_from (on a verified domain for live
environments), use coss.com's default email or yours (it must contain {{{confirmation_url}}}), and
can send the contact to confirmed_redirect_url afterwards. While double opt-in applies,
status: "subscribed" is refused (double_opt_in_status); pass double_opt_in: false for someone
who already confirmed elsewhere.
await ...({
: "Acme <news@acme.com>",
: "https://acme.com/welcome",
});
const { : } = await ...({
: "new@example.com",
: true,
});
// contact?.status === "pending"
// Sent again at most once a day, three times in all.
await ...(?. ?? "");Confirmation links expire after 7 days. Contacts that never confirm are deleted
30 days after they were asked (see data retention),
except one who had opted out (unsubscribed before, or left a topic): they go back to
unsubscribed, so their opt-out stays.
Confirming sends a contact.confirmed webhook.