Custom Preference URLs
Brand the preference-center link recipients click in the email body, while ArtaMail continues to sign tokens and process consent. You can keep Gmail one-click on ArtaMail, or move everything to your own domain.
Choose an approach
| Approach | preferences_url_template | Body links | List-Unsubscribe |
|---|---|---|---|
| Hybrid (recommended) | Leave empty | Custom URL + {{unsubscribe_token}} | ArtaMail /api/u/{token} (one-click works out of the box) |
| Default ArtaMail | Leave empty | {{unsubscribe_url}} | Same ArtaMail URL |
| Full custom domain | Set (e.g. https://prefs…/manage?token={{token}}) | {{unsubscribe_url}} uses your template | Same custom URL — you must proxy GET and POST |
preferences_url_template, it applies to {{unsubscribe_url}}, typed {{unsubscribe_<slug>}}, and the List-Unsubscribe header. There is no separate toggle for Gmail one-click. If you only want a branded "Manage preferences" link in the email body, leave the setting empty and use the hybrid recipe below.Hybrid: custom manage link + ArtaMail one-click
Best when you host your own preference UI but do not want to implement a one-click POST proxy. Recipients see your domain in the email; mail clients (Gmail, etc.) still POST to ArtaMail for RFC 8058 one-click unsubscribe.
- In Settings → Subscription consent, leave Custom preferences URL empty.
- In marketing templates, build your manage link with the bare token (do not rely on
{{unsubscribe_url}}for branding — that variable follows the org template or ArtaMail default):
<a href="https://app.example.com/preferences?token={{unsubscribe_token}}"> Manage email preferences</a>Your page reads the token, loads data from ArtaMail, and saves preferences via the APIs below (GET data + POST preferences). You do not need a POST handler for List-Unsubscribe — that stays on https://artamail.artatol.net/api/u/{token}.
{{unsubscribe_token_<type_slug>}} the same way.unsubscribe or /u/ skip click tracking. If your path is something like /preferences, the href may be rewritten through the click tracker (GET still reaches your page after redirect). Prefer a path that includes unsubscribe if you want to skip tracking entirely.Full custom domain (optional)
Use this when you need a white-label URL in both the email body and List-Unsubscribe (same domain everywhere). In Settings set a template such as:
https://prefs.acme.com/manage?token={{token}}At send time ArtaMail replaces {{token}} with a signed HMAC token. That URL is used for {{unsubscribe_url}} and for List-Unsubscribe. This setting is unrelated to double opt-in success redirects (those use per-template confirm_success_redirect_url).
preferences_url_template on each account when you want a fully custom domain per product. See the Multiple Products guide. For shared contacts in one account, see shared contacts (advanced).Template variables
| Variable | Replaced with |
|---|---|
{{unsubscribe_url}} | Full preference URL — org preferences_url_template or ArtaMail default (also used for List-Unsubscribe) |
{{unsubscribe_<type_slug>}} | Full URL scoped to a subscription type (same org template rules) |
{{unsubscribe_token}} | Bare signed token — build your own body URL (hybrid pattern) |
{{unsubscribe_token_<type_slug>}} | Bare typed token for a subscription type |
APIs for your preference page
Whether you use the hybrid or full-custom approach, the preference UI on your domain loads and saves consent through ArtaMail. Token verification and consent updates stay on our side.
GET — load preference data
Users click links in the email body. Your page should read the token from the query string or path, then:
GET https://artamail.artatol.net/api/u/{token}/dataResponse includes locale, resolved copy (all page strings for the contact's language), optional oneClickCopy, orgName (brand), legalEntityName, and localized subscription subtypes. Use copy.title, copy.button_save, etc. in your UI — or use ArtaMail custom HTML with placeholders like {{title}}. Full reference: Preferences Data API.
Example response
{ "orgId": "550e8400-e29b-41d4-a716-446655440000", "orgName": "SuperWidget", "legalEntityName": "Acme Holdings s.r.o.", "email": "[email protected]", "locale": "cs", "copy": { "title": "Předvolby e-mailu", "subtitle": "Vyberte, jaké e-maily chcete dostávat.", "footer": "Powered by ArtaMail", "button_save": "Uložit předvolby", "button_unsubscribe": "Odhlásit se ze všeho", "type_title": "Předvolby e-mailu" }, "oneClickCopy": { "success_title": "Odhlášeno", "success_message": "Byli jste odhlášeni z našeho seznamu." }, "type": null, "subtypes": [ { "id": "subtype-uuid", "slug": "weekly-digest", "typeSlug": "newsletter", "label": "Týdenní přehled", "channel": "marketing", "sortOrder": 0, "subscribed": true } ]}Subtype labels are already localized. Save changes with POST /api/u/{token}/preferences (subtype slugs as JSON keys).
POST — mail client one-click (full custom domain only)
Required only when preferences_url_template is set. Gmail and other clients send an RFC 8058 one-click unsubscribe POST to the URL in the List-Unsubscribe header — the same custom URL you configured. Your server must accept that POST and proxy it to ArtaMail:
POST https://artamail.artatol.net/api/u/{token}Content-Type: application/x-www-form-urlencodedList-Unsubscribe=One-Click?redirect=1 to show a localized success page at /preferences/{token}?one_click=1 (uses org one_click_copy). With the hybrid approach, leave the template empty so this POST stays on ArtaMail.ArtaMail hosted UI
Default landing after GET /api/u/{token} is /preferences/{token}. Legacy /unsubscribe/* URLs redirect permanently.
Custom HTML templates
On subscription types with custom HTML, wrap form-only sections (header, intro, footer) in artamail-form-only so they hide after save. Success content lives in #artamail-success inside {{subtypes_form}}. Optional post-save CTA: {{success_button}} or class artamail-success-cta ({{success_button_class}}). Injected and {{success_button}} links use target="_top" so navigation leaves the hosted iframe. If you build your own <a> with {{success_button_href}}, add target="_top" as well.
Example reverse proxy (Node) — full custom domain
Only needed when List-Unsubscribe points at your domain (preferences_url_template is set).
// POST /manage?token=... → ArtaMail one-click unsubscribeexport async function POST(req: Request) { const token = new URL(req.url).searchParams.get('token'); if (!token) return new Response('Missing token', { status: 400 }); const body = await req.text(); const res = await fetch(`https://artamail.artatol.net/api/u/${token}`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body, }); return new Response(null, { status: res.ok ? 200 : res.status });}