A small business splitting 400 customers into two groups of 200 will see a difference between them. That difference is almost always noise. Understanding when a result is real is the difference between improving your messaging and randomly changing it every month.
Test big differences, not wording tweaks
With a small list you can only detect large effects. A 2% improvement from changing 'Hi' to 'Hello' is undetectable and probably does not exist. A change from 'click here to confirm' to 'reply C to confirm' can move response by a third, and that you can see.
Not worth testing at this size
- Greeting wording
- Emoji or no emoji
- Sending at 10am vs 11am
- Minor punctuation
Worth testing
- Reply vs click as the action
- Named person vs business name
- With an offer vs without
- Day before vs same day
Split deterministically
Hash the customer ID with the test name so a given person always lands in the same arm. Random assignment per send means someone gets variant A on Monday and B on Thursday, which measures nothing.
import { createHash } from "node:crypto"; export function variantFor(customerId: string, testName: string) { const hash = createHash("sha256") .update(`${testName}:${customerId}`) .digest(); return hash[0] % 2 === 0 ? "a" : "b";} // Record it in utm_content so the arm follows the click all the way// through to the conversion.const link = tagged(url, { campaign: "appointment_reminder", content: `reply_vs_click_${variantFor(customer.id, "reply_vs_click")}`,});Decide the sample size before you start
Not after you look at the numbers. A rough rule for a small list: you need roughly a few hundred per arm to reliably detect a change of ten percentage points on a rate around 50%. Smaller effects need far more. If you cannot reach that, accumulate across several sends of the same campaign instead of calling it after one.
Do not peek and stop early
Checking daily and stopping when the numbers look good is the most common way small tests produce false results. Every peek is another chance for noise to look like signal. Set the end condition up front and hold to it.
Measure the outcome, not the click
A variant that gets more clicks and fewer bookings has lost. Always evaluate against the action that pays you — confirmed appointment, invoice paid, order placed — with the variant carried through in utm_content. Tracking it end to end.
Watch the metric nobody tracks
Opt-out rate per variant. A message that converts slightly better while generating twice the unsubscribes is destroying an asset to win a quarter. Track it alongside the win, and treat a rising rate as a failed test regardless of the conversion number.
The alternative to testing is a holdout
If your list is genuinely too small to test variants, do not test variants. Run a holdout instead and measure whether the campaign works at all — a far more valuable question, and one a small list can answer. How.
Next step
Generate a tagged link for whatever you send next with the UTM builder, see what this looks like in your industry, or compare the services that can send it on the providers page.