Every campaign starts from scratch
You split a list three ways, send, wait two days, and pick a subject line. Next month is a different promotion with different copy, so you split three ways again. What you learned about urgency or social proof stays in a slide deck. The test tool never sees it.
The click numbers don't help much either. Corporate link scanners open every link in every email, so the click count your email service reports includes machines. And nobody counts the recipients who unsubscribed because of a pushy subject line.
Bandit's email campaigns fix those three things. Each recipient gets their own draw of the copy. Bandit counts the click a person makes on your site. An unsubscribe costs the version that caused it. And results roll up by framing, so the next campaign starts with what the last one learned.
What Bandit does, and what it does not
Bandit never holds your list, never sees your email service credentials, and never sends email. Your send code asks Bandit what each recipient should get, and you send it with the service you already use.
A campaign is a set of slots, such as subject, preheader, hero, and call to action. Each slot is an experiment with its versions. Every recipient gets one version per slot, picked for them. That is the same model as a whole-page experiment, where one reward is credited to every slot the person saw.
Ask for copy
Per recipient, or one plan per chunk
Send
Your email service
Click
Link carries a signed tag
Report
Your site posts the click
Learn
Credit every slot shown
Asking for copy
There are two ways to get copy for a send.
Render. Post one recipient, or up to 10,000 per call, to the render endpoint. Each recipient gets their own draw and a set of signed link tokens.
Plan. For large sends, ask for a campaign plan instead. A plan holds each slot's selection probabilities and the values the SDK needs to sign tokens. The SDK picks each recipient's versions locally with no network call, from a hash of the recipient id. After the send it reports which versions went out. A plan is good for 50,000 recipients by default, configurable up to 250,000, after which the SDK asks for a fresh one. A 2 million recipient send with the default makes 40 calls, and the split updates between chunks as clicks come in.
Your template marks slots with {{ bandit.subject }} style placeholders. The SDK fills them and rewrites the links in your own process, so your HTML and merge data never leave your servers.
How clicks get counted
By default Bandit doesn't redirect your links. It appends a signed tag, ?bt=..., to each one. The recipient goes straight to your site, and your site reports the click to Bandit with the tag. The tag carries a hash of the recipient id, never the raw id, and an index into the campaign's link list, never a URL.
If you'd rather not touch your site, choose Redirect proxy when you create the campaign. Links then pass through Bandit, which records the click and redirects.
Before you send, choose Run check on the campaign page. Bandit fetches each destination with a test tag, follows any redirects, and reports OK, Param stripped, SDK not detected, or Unreachable for each link. A login redirect that drops the query string shows up here, before you send.
Filtering out bots
Every click is stored. A click counts toward the result only when it is the recipient's first click in that campaign and it passes three checks:
Known scanner or bot
User agents such as Proofpoint, Mimecast, Safe Links, Barracuda, curl, and headless Chrome
Too fast
Clicked less than 5 seconds after the campaign was sent
Burst
3 or more different links from one email within 2 seconds
The campaign page shows four numbers: Human-filtered, Raw, Bot-filtered, and Duplicate touches. The human-filtered number is the headline, and it will often sit below what your email service reports. The difference is the scanner traffic.
Bandit does not use opens. Apple Mail Privacy Protection loads every image for many recipients, so an open count says little about a person.
Unsubscribes cost something
When a recipient unsubscribes, your unsubscribe handler sends Bandit the tag from the link. Bandit records a negative reward against the versions that recipient got.
How negative? Bandit sizes it from your own history, counting one unsubscribe as worth your past ratio of counted clicks to unsubscribes. You can override the number per call.
Say your account has 2,400 counted clicks and 12 unsubscribes so far. One unsubscribe then costs 200 clicks. Two subject lines go out to the same number of people:
| Version | Clicks | Unsubscribes | Net, in clicks |
|---|---|---|---|
| "Last chance: 30% off ends tonight" | 300 | 2 | -100 |
| "Your spring picks are in" | 260 | 0 | 260 |
A version that loses one subscriber per 200 clicks, your usual rate, nets zero. The pushier line lost one per 150 clicks, faster than your baseline, so it comes out behind. Before your first unsubscribe there is no ratio yet, so the first one costs as many clicks as you have counted so far, or 100 if you have none.
Carrying learning into the next campaign
When you add a version in the dashboard, Bandit classifies it by strategy, tone, call-to-action style, and emotional hook, and files it under a tag for each label, such as urgency or social proof. Versions with the same label share a tag across campaigns. A label Bandit hasn't seen before becomes a new tag for your account.
When a sent campaign is finished, choose Complete & fold up. Each tagged version's results fold into its strategy's record. Do it once the conversion window has closed, because you can only do it once.
When the next campaign starts sending, each tagged version starts from its strategy's record instead of from zero. It inherits 20% of the strategy's evidence, capped at 20 observations' worth, so one strong past campaign gives the new copy a head start without locking it in. A tag with no record of its own borrows from its parent tag. The campaign page's Strategy Performance, Across All Campaigns table shows the rolled-up result for every tag.
Limits
- Clicks only count on pages you control. In the default mode, an app store badge, a partner site, or a PDF can't report a click.
- Some setups strip query strings. Run the link check before every send.
- A forwarded email counts for the original recipient. Only the first click per recipient counts, which limits the damage.
- Hard bounces still count as sends. They spread evenly across versions, so they add noise, not bias.
- Pooling across companies is not built. Your strategy records learn from your campaigns only.
- Email campaigns stay on per-slot credit. The joint model that can credit slot combinations is not available for a bundle that sends email.
How to turn it on
- In the dashboard, open Campaigns and create a campaign. Choose Link parameter or Redirect proxy for click tracking, and set a conversion window. The default is 7 days.
- Choose Add experiment once per slot, and add the versions for each.
- Choose Run check to test your links.
- When the campaign is sending, have your send code call render or plan for copy and send with your own service.
- Report clicks from your site, and unsubscribes from your unsubscribe handler, with the tag from the link.
- After the conversion window, choose Complete & fold up.
The lifecycle and email page shows the strategy table and the send steps.
The copy changes every campaign, and Bandit keeps the record of which framing worked.
Ready to try algorithmic testing?
Stop wasting traffic on losing variants. Bandit's multi-armed bandit algorithms automatically shift traffic to your best-performing treatments in real time.
Start free trial