Skip to content

Campaigns

A campaign is a named, time-bounded push that bundles paywalls, journeys, and copy variants under shared targeting and reporting. Use one when you want a coordinated promotion — Black Friday, a fundraiser, a win-back push — and to measure which version of the message wins.

A campaign isn’t its own delivery channel. It’s a wrapper that piggy-backs on the channels you already have:

  • The paywall on the publisher’s site — when a visitor matches one of your existing paywall rules, and that rule is attached to a running campaign, the SDK shows that visitor a variant of the paywall instead of the bare version.
  • Emails sent by attached journeys — variants flow into the journey’s send_email step bodies and subject lines.
  • Webhooks fired by attached journeys — the campaign and variant id are included in the payload, so your CRM / Slack can branch on them.

Visitors don’t see anything explicitly campaign-related. They see the paywall they would have seen anyway — with the variant the campaign assigned to them.

You want…Use
Always-on access control on a section of your sitePaywall rule
Time-limited promotion with a goalCampaign
Headline / copy A/B test on the same paywallCampaign
Reactivate lapsed subscribers over the next 14 daysCampaign that contains a Journey

A paywall rule is “what content is gated and how”. A campaign is “this push we’re running, ending Date X, measured by Goal Y, testing variants A/B/C.”

StatusMeaning
DraftYou’re still configuring it. Readers never see it.
ScheduledConfigured and ready, but its start date is in the future.
RunningActive for visitors in the audience. Variants are being assigned and stats accumulate.
ConcludedEnded — either you promoted a winner or the end date passed. The winner’s copy is live; other variants stop showing.
ArchivedHidden from the main list. Use this for old campaigns you want off the dashboard but don’t want to delete.

The list page has tabs across the top so you can filter to just running, just concluded, etc.

From the campaigns list, click Create campaign. Provide:

  • Name — descriptive (“Spring fundraiser 2026”, “Black Friday push”).
  • Description — optional team-only context.
  • Goal target — number of new subscriptions (or your goal metric) you’re aiming for. Used in the dashboard summary; it does not gate the campaign.

The campaign starts as a draft. No reader sees it yet.

This is the load-bearing step. Open the campaign you just created — the Targets card is at the top.

Click Attach and pick:

  • A paywall rule — usually the rule whose copy you want to test. The campaign’s variants will replace blocks in that rule’s layout when a visitor matches it. You can attach more than one rule if the campaign should drive several paywall surfaces at once.
  • A journey (optional) — if you want emails or webhooks to be part of the same coordinated push, attach a journey. The journey’s send_email and fire_webhook steps then carry campaign + variant ids through.

Without at least one target, the campaign is dormant — visitors flow through paywalls and never get bucketed into your variants. No targets = no traffic = no stats.

A variant is one version of the campaign’s copy / layout. You typically want 2–4 variants:

  • One Control — the baseline, usually a copy of what the paywall already says.
  • One or more Challengers — your alternative angles.

Click Add variant to open the variant editor (a dedicated page). Fill in:

  • Name — e.g. “Control”, “Urgency angle”, “Value angle”.
  • Is control? — check on exactly one variant.
  • Traffic weight — how often this variant is picked relative to the others. Equal weights = even split.
  • Blocks — visual editor. Heading / Text / Image / CTA / Divider / Spacer. Tokens like {{customer.name}} are expanded at render time.

To override an existing block in the control’s layout, give the new block the same id as the control’s block. Otherwise the variant’s blocks append to the layout. The “Advanced JSON…” toggle exposes overrides the visual editor doesn’t surface (different productIds, a message shadow, custom CSS, etc.).

A control variant whose overrides are empty is fine — it just renders the underlying paywall unchanged.

On the Variants section header, click Generate with AI. Provide a brief (“lean into urgency”, “more value-focused”) and a count, and the agent drafts variant proposals you can accept one-by-one. Accepted proposals become real variants you can then edit by hand.

When at least one target and at least two variants are in place, click Activate at the top of the campaign. Status flips to running.

From this point on, every visitor matching one of the attached rules’ conditions is bucketed into one of the variants (deterministic, stable per visitor) and the variant’s overrides are merged onto the rule before the SDK renders it. Each impression and conversion is automatically tagged with the campaign + variant id.

Once traffic flows, the Variants table updates with:

  • Impressions — paywall views attributed to this variant.
  • Conversions — Subscribe-clicks attributed to this variant.
  • Rate — conversions ÷ impressions.
  • P(winner) — the probability that this variant has the highest true conversion rate of all variants in the campaign. Numbers across all variants always sum to 100%.

The bar fills proportionally and turns green with a check mark when it crosses the 90% promote threshold.

How to read P(winner):

  • Below 50% — variant is unlikely to be the best. Wait or rule it out.
  • 50–80% — leading, but the data is still noisy. Don’t promote yet.
  • 90% or higher — strong evidence this variant beats the others. Promote.

When a variant clears 90% and every variant has at least 200 impressions, click Promote on its row.

Promoting:

  • Marks the variant as the winner (promoted_at is stamped).
  • Moves the campaign to concluded.
  • Folds the winner’s copy into the underlying paywall rule — even visitors who weren’t in the test now see the winning copy.

If you try to promote before the gates pass, the dashboard explains why and offers a force-promote confirmation. Use force-promote when the campaign window is closing and you’re willing to ship on a smaller sample. Don’t force-promote on day one.

Concluded campaigns stay on the Concluded tab. If you want them out of the way, archive them — they move to the Archived tab and stop appearing in default lists.

  • Pick a single decision metric (usually subscription_started) and stick with it for the campaign. Adding a second metric mid-flight invalidates the Bayesian math.
  • Don’t promote on day one even if the leader is at 95%. With fewer than 200 impressions per variant, it’s almost certainly noise.
  • Two variants is fine. Four is the sweet spot. Beyond five, you’ll need a lot more traffic for any single variant to clear 90%.
  • One campaign per paywall rule, per time window. If two running campaigns target the same rule, behaviour is undefined for now — keep them serial.

Nothing visible. The paywall they would have seen still appears at the same trigger (URL match, scroll depth, exit intent — whatever the underlying rule says). The only difference is that the heading, body, CTA, or whichever blocks differ between the variants, are pulled from the variant they were bucketed into. The same visitor sees the same variant on every visit until the campaign concludes.

If you’ve used Latch’s existing experiments, campaigns are the bigger-picture version: experiments test variants of a single paywall rule, while campaigns wrap one or more rules + journeys with shared targeting, lifecycle, and reporting. New work should use campaigns.