Skip to main content
An A/B test sends two to four versions of a campaign message to a test group. When the test window ends, Polymorfa compares the versions on the outcome you choose and sends the winning message to the reserve: everyone not in the test group or the optional holdout. If no version is clearly ahead, the campaign pauses and the reserve gets nothing. A/B tests are a beta. A team owner or admin enrolls the team on the Campaigns page of the console. Until the team is enrolled and the beta is offered to it, creating or duplicating an A/B campaign, changing its variants, launching it and resuming it return 403 feature_unavailable. A/B campaigns follow every other campaign rule in Send a campaign, including plans, sending numbers, opt-outs and send windows.

How the audience is split

At launch, each recipient is assigned once to one of three groups. The assignment is saved and does not change when a send is retried or the campaign is paused and resumed. The split is by chance, so group sizes are close to the percentages rather than exact. A recipient skipped for another reason, such as an opt-out or a missing variable, keeps its group but is not sent.

Create an A/B campaign

Send variants and variantStrategy when you create the campaign. Each variant is a text message; {{variable}} placeholders are filled per recipient as in composed messages, and every variable needs a value or fallback, as described in Send a campaign. An A/B campaign sends its variants, so it cannot also set templateId.
A request that breaks a rule returns 400 invalid_parameter with error.param naming the field. While the campaign is an unlaunched draft, send new variants or variantStrategy with an update to change them, or null for both to make it a broadcast. After launch an update returns 409 state_conflict. On the Platform API, send the same fields to POST /platform/campaigns and PATCH /platform/campaigns/{campaignId}. In the console, choose A / B test when you create a campaign.

How the winner is chosen

The test window starts when the campaign starts sending: at launch, or at scheduledAt for a scheduled campaign. Test-group recipients are sent during the window. Reserve recipients stay queued until a winner is chosen. When the window ends, Polymorfa decides once:
  1. Every test send must be settled. A test recipient that is still queued or sending, whose send outcome is unknown, or whose result arrived after the deadline makes the test inconclusive.
  2. For each variant, the rate is the number of test recipients delivered, read or replied to by the deadline, divided by the test recipients sent by the deadline. Results that arrive later do not change the decision.
  3. Every variant needs at least 20 sent test messages.
  4. The winner’s rate must be clearly higher than every other variant’s: the lower bound of its 95% confidence interval (Wilson score) must be above the upper bound of each other variant’s interval. A higher rate alone, a tie, or overlapping intervals is inconclusive.
When there is a winner, the reserve is sent the winning message and the campaign continues as usual. experimentOutcome on the campaign becomes { "state": "promoted", "winnerKey": "story" }. When the result is inconclusive, the campaign pauses and the reserve stays unsent. experimentOutcome becomes { "state": "inconclusive", "reason": "insufficient_evidence" } and a campaign.paused event is recorded. The decision is final: later results do not release the reserve, and resume returns 409 state_conflict. Stop the campaign to cancel the reserve, or duplicate it to run a new test. Plan the window so the test group can be sent and answer in time. A send window, a pause, or throttling that keeps test recipients queued past the deadline ends the test inconclusive.

Follow the results

GET /messaging/projects/{projectSlug}/campaigns/{id}/analytics returns an experiment object for an A/B campaign, and null for a broadcast:
The response also carries the campaign’s other analytics fields. outcomeRate counts every result received so far, so after the deadline it can differ from the rate the decision used. The Platform API returns the same object from GET /platform/campaigns/{campaignId}/analytics. The console shows the results on the campaign’s page.

Leaving the beta

When a team withdraws from the beta, or the beta is no longer offered to it, new A/B campaigns are refused. A running A/B campaign pauses before its next send with a campaign.paused event, and its reserve stays unsent. Messages already sent, saved assignments and results remain readable, and a paused campaign can still be stopped. Resuming it requires the beta again.

Limits

  • Test sends of an A/B draft are not supported; they return 409 state_conflict.
  • A/B tests send from linked WhatsApp numbers and test numbers. A campaign that would send from an Official (Cloud API) number pauses before its first send.
  • An A/B campaign cannot use a template.