The engine takes on what a sending platform usually does: it parses outgoing HTML, rewrites links so that clicks go through the tracking domain, and inserts an open pixel. It works only together with the vendor’s analytics service (sparkpost-signals) — the events go to it.
Three independent switches. The top pixel, the bottom pixel and link rewriting are enabled separately; you can take only what you need.
The tracking domain is the vendor’s by default, but it can be replaced with your own: the client’s domain is pointed at their infrastructure with a DNS record. For European senders there is a regional variant, and it is mandatory, not merely advisable.
Individual links are excluded right in the markup — with an attribute the engine removes from the delivered message. That way the unsubscribe link stays untracked instead of turning into a click through someone else’s domain.
Secure links are off by default and require a properly configured domain with a certificate.
What to do when the HTML cannot be parsed is decided by a setting: either the message bounces or it goes out unchanged. In both cases the error is written to the log.
We are building the same thing on our own. The Hub issues and maintains tracking domains itself: TrackingDomainManager sets up the client’s domain on the node, obtains a certificate and keeps it renewed.
The difference is fundamental: at the vendor clicks go through its infrastructure, for us — through our node. For a boxed product this is decisive: data about the client’s recipients’ clicks must not go to a third party.
The experience in this entry is directly useful to us — the set of decisions is the same: where to put the pixel, how to exclude the unsubscribe link, what to do with unparsable markup.
Decisions that have to be made — both at the vendor and on your own side:
| Decision | Options | What to watch |
|---|---|---|
| open pixel | top, bottom, both | the bottom is more reliable: some clients truncate long messages |
| link rewriting | on or off | without it there are no clicks, but the message stays untouched |
| tracking domain | the vendor’s or your own | your own means recipient trust and your own data |
| secure links | off by default | require a domain with a certificate |
| unparsable markup | bounce or let through | bouncing loses messages, letting through loses data |
Always exclude the unsubscribe link. A click on it through someone else’s domain is an extra point of failure exactly where failure is most expensive: a recipient who could not unsubscribe clicks “spam.”
For European senders the regional variant is mandatory — this is a requirement, not a recommendation.
# at the vendor these are settings of the analytics block <signals> engagement-tracking sparkpost tracking-domain track.example.com html-edit-error-mode bounce</signals>
what people get wrong and how it ends3 mistakes▶
§ 11.1.6.2.3
§ 11.1.6.2.3
§ 11.1.6.2.3
1 relation
grep -n -A6 '^<signals' /etc/pmta/config dig +short track.example.com
2 articles
◇Hand a message to a webhook instead of a receiverThe queue sends the message as a POST request in the form of a JSON object; only a 2xx response counts as success.◇Markup parsing and editingOpen and click tracking in sparkpost mode edits the message markup with the built-in gumbo-parser; by default a message whose markup could not be parsed is bounced.