SendQL
Consent and membership
Subscriptions, opt-outs, suppression, and testing membership of a list or another segment.
Deliverability rules are not a separate system bolted onto SendQL. They are terms in the language, and they read like English.
Consent
Four forms, covering the four questions worth asking:
subscribed to "product-updates"
opted out of "promos"
unsubscribed from all
suppressed
A topic is a consent grouping — a subscription a contact can opt into or out of independently of every other. Each topic has a default, opted in or opted out, and a contact who has never stated a preference for that topic takes it. So the question each term asks is about the contact’s effective status:
| Term | Matches |
|---|---|
subscribed to "marketing" | Effectively opted in — by their own choice, or by the topic’s default — and not unsubscribed from all |
opted out of "marketing" | Effectively opted out — by their own choice, or by the topic’s default |
The two are nearly, but not quite, negations of each other. A contact who is opted in to the topic but has unsubscribed from everything is in neither set: they are not mailable under the topic, yet they never opted out of it.
You write the topic’s name, and the name is not checked against your
topics. A misspelt one (subscribed to "markting") is accepted and matches
nobody, so copy names rather than retyping them.
unsubscribed from all is the global opt-out — the “unsubscribe from everything”
link, not a per-topic preference.
suppressed is different in kind, and it is the one to understand. A
suppressed contact is one you cannot mail: a hard bounce, a spam complaint, a
manual block. It is not a preference, it is a deliverability fact, and ignoring
it is how a sender damages its reputation.
Which is why almost every segment you write should end the same way:
attr.plan = "trial" and not suppressed
Get in the habit. not suppressed costs six characters.
Membership
Two forms, both taking the quoted key of the list or segment:
in list "beta-testers"
in segment "power-users"
A list is a named bag of contacts — something you add people to, by hand or
from a workflow (add to list "engaged").
A segment is a saved SendQL query. in segment "power-users" composes one
segment into another, which is how you keep a complicated definition in one place
instead of copy-pasting a predicate into nine campaigns:
in segment "power-users" and not exists(activity.login within 30d)
Both compose with not:
in list "beta-testers" and not in segment "power-users"
When you save a segment, each key is looked up and stored as the list’s or segment’s id, so the saved definition keeps pointing at the same list even if another one is later created under the old key. Reopen the segment and you will see the id where you typed the key; writing the id yourself is equally valid. A key that names nothing does not block the save: the segment is saved as invalid, with a reason that names the key:
in list "beta-tester": no List has this key or id in this organization
They are strings, so they can be anything
Topics, lists and segments are all quoted strings, never bare identifiers. That is a deliberate design decision with a pleasant consequence: their names are not constrained by the language’s grammar at all.
subscribed to "timeout" and in list "count"
Both of those names are reserved words, and
both are perfectly fine, because a quoted string can never be confused with a
keyword. Hyphens, spaces and punctuation are equally unproblematic —
"product-updates" needs no escaping or special handling.
A realistic deliverability preamble
Putting the consent terms together with the rest of the language, a production-grade marketing segment usually looks something like this:
// Reachable, engaged, opted-in — and demonstrably not a lost cause.
subscribed to "marketing"
and not suppressed
and not unsubscribed from all
and count(bounce within 90d) = 0
and count(complaint) = 0
and count(open within 60d) >= 1
The last three lines are worth stealing. Filtering out recent bouncers and anyone who has ever complained, and requiring a single open in two months, is most of what list hygiene actually is — and here it is just five more terms in the same expression, checked by the same type checker as everything else.