> For the complete documentation index, see [llms.txt](https://docs.amply.tools/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.amply.tools/user-guide/testing-and-rollout.md).

# Testing and rollout

Every campaign change goes live the moment you save it and move the campaign to **Active**. There is no app release, no review window, and no store approval. That release-free control is what Amply's orchestration is for — and it's also why you need a testing routine. This page covers how to validate a campaign in staging, how to stage the rollout yourself using audience targeting, and how to pull a campaign instantly if something is wrong.

**Use this when** you are about to publish a campaign to real users, or a live campaign is misbehaving. **Don't use this when** you are still iterating on the rule design and haven't yet decided what to validate.

{% hint style="info" %}
To see a campaign on your own phone before anyone else does, drafts included, use [Test on device](#test-on-device). It shows the campaign and counts nothing. To test the whole path, trigger and audience included, use an Active campaign with an audience of one, as described below.
{% endhint %}

## Test on device

**Test on device** opens any campaign, drafts included, in the real app on your phone. Scan a QR code and the campaign appears. Nothing about it is counted.

Your app needs SDK 0.15.0+ and must pass incoming links to Amply (a one-time change, see [Forwarding links to Amply](/developer-guide/handling-deeplinks.md#forwarding-links-to-amply)). Older app versions ignore the link.

### Set each app's scheme once

In each application's settings, fill in **Deeplink scheme**: the scheme the app opens links with, such as `myapp` for `myapp://…`. Enter the scheme only, without `://`.

In Amply your iOS and Android apps are separate applications, so each has its own scheme. They can be the same or different: `myapp` on both, or `myapp` on iOS and `myapp-android` on Android, whatever each app registers. An app without a scheme can't be opened from the QR code. **Test on device** lists every app the campaign targets with its platform and scheme, and flags any app that has none, with a link to its settings.

### One code for both platforms

When the campaign's apps share one scheme, for example `myapp` on both iOS and Android, there is one QR code for both platforms. The phone that scans it decides:

* The page it opens sees whether it is an iPhone or an Android phone, and opens the campaign's app for that platform.
* If the campaign targets several apps on that platform, the page shows a button for each, and you pick one.
* If the campaign targets no app on that platform, or that app has no scheme, the page says so instead of opening anything.
* Opened on a computer, the page asks you to scan the code with the phone.

When the apps' schemes differ, **Test on device** shows **Open in** with a choice of app, and the code opens only the app you pick.

### Share the link with testers

The link doesn't expire and isn't tied to a phone. Scan it on as many phones as you like, as often as you like, or copy it and send it to your testers: tapping it on a phone works the same as scanning. The same campaign always has the same link, and it stops working only when the campaign is deleted.

### Show a campaign

1. Open the campaign and click **Test on device**.
2. Choose **Check targeting**:
   * **Off**: the campaign shows right away.
   * **On**: Amply first checks this phone against the campaign's audience, then shows the campaign if it matches. The trigger is ignored either way.
3. If **Open in** is shown, pick the app.
4. Scan the QR code with the phone's camera. A page opens and hands the link to your app, which shows the campaign.

Each **Check targeting** setting has its own link. A mini-app campaign shows the published version it uses.

### When the phone doesn't match

With **Check targeting** on, a phone that doesn't match sees a list of every audience condition, each marked as met or not, with this phone's actual value next to it. That is usually the fastest way to find why a campaign doesn't reach someone.

Frequency limits never stop a test. They are listed for information, for example that a limit would block a normal show right now.

### What is and isn't real

* **Not counted:** no impression, no result, nothing in the campaign's statistics or goals, nothing sent to your analytics, no survey answers, no tracked events.
* **Real:** what the campaign's buttons do. A link opens, a purchase is a real purchase.

Agents connected over [MCP](/getting-started/ai-assisted-integration.md) can make the same link and open it on a simulator.

## Why "no release required" matters

Changing in-app behavior normally means: code change → internal QA → store submission → store review (often days) → phased store rollout → users finally see the change. Amply skips all of that for anything you express as a campaign.

* **Change a trigger**: edit the **When** step, save. Users who start a session after the change use the new rules.
* **Change the audience**: edit the **Who** step, save.
* **Change the deeplink URL**: edit the **What** step, save.
* **Pull the campaign**: change state from **Active** to **Cancel**. New evaluations stop immediately.

The app code — the deeplink handler, the popup screen, the SDK — does not change. Only the rules the dashboard evaluates change.

## Phase 1 — Validate in staging before publishing

Only **Active** campaigns are evaluated. To test without exposing users, narrow the **Who** rules so the campaign matches only your test device, then move it to **Active**. Keep the narrow rules until you have verified behavior, then widen.

### Step 1: wire the staging build to the same project

Your mobile team runs a staging build that points at the same Amply project used for production. If they run a separate project for staging, make the test campaign in that project instead — and remember to re-create it in production after validation.

### Step 2: make yourself match the audience

The cleanest way to test: temporarily narrow the campaign to an audience that is only you.

* Set a **Custom Property** condition like `qa_tester == "your-name"` and set that property from the staging app.
* Or narrow by **Country**, **OS Version**, or **App Version** to a combination only your test device matches.

If the campaign will eventually target everyone, keep the narrow version Active until you have verified behavior, then widen the audience.

### Step 3: fire the trigger and confirm delivery

1. Ensure the campaign is **Active** while you test (Draft campaigns are skipped).
2. Fire the **Triggering event** by doing whatever action calls `Amply.track(...)` in the app, or by restarting the app if the trigger is `SessionStarted`.
3. Watch the deeplink listener (for Deep Link campaigns) or the native review sheet (for Rate & Review).
4. If nothing happens, check the campaign detail page for the trigger count — it increments when a match is recorded, regardless of whether the action visibly succeeded.

### Step 4: widen the audience and move to production use

Once behavior is correct:

1. Edit the **Who** step to the real production audience.
2. Save. The campaign is now targeting real users but still in Active state on your test device, so double-check once more.

### Troubleshooting

| Symptom                                                         | Likely cause                                                                                 |
| --------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| No trigger count increments                                     | Campaign is in **Draft**, or the triggering event name has a typo (they are case-sensitive). |
| Trigger count increments but nothing visible happens in the app | Deeplink handler not registered, or the URL scheme doesn't match what the app expects.       |
| Some users trigger but not others                               | Audience conditions exclude them. Check country, app version, and custom property filters.   |
| Campaign fires too often                                        | **Frequency Limits** not set or set too permissively.                                        |
| Campaign does not fire again for the same user                  | Frequency limit was hit. Increase the window or raise the cap.                               |

## Phase 2 — Control who sees it (phased rollout)

Amply does not ship a percentage-based rollout slider today. You get the same effect by widening the audience in steps.

1. **Start narrow.** When moving from Draft to Active, keep the **Who** targeting tight: one country, latest app version, maybe a specific custom property.
2. **Wait, then measure.** Check the campaign detail view for trigger counts and any downstream events (for example, post-popup `feedback_given`). Cross-reference with product analytics for any regression on the core KPIs.
3. **Widen.** Edit the **Who** step and remove one constraint (add more countries, drop the app-version filter). Save.
4. **Repeat** until the audience is what you want it to be.

Because edits to an Active campaign take effect within minutes, each widening step lands in minutes, not days.

## Instant rollback

If a live campaign is hurting users — wrong screen, broken deeplink, prompt firing too often — stop it immediately:

1. Open the campaign.
2. Change state from **Active** to **Cancel** (or use the state control on the list view).

From that moment on, the campaign stops matching and no new deliveries happen. Work that was already dispatched to an in-flight session may still complete, but nothing new starts.

A cancelled campaign stays in the list. You can fix the issue, then either:

* Return it to **Active** (same campaign, same ID, keeps historical counts), or
* Duplicate it into a new **Draft**, edit, validate, activate (use this if the fix is significant).

## Checklist before you move a campaign to Active

* [ ] The campaign ran end-to-end on a staging or real test device.
* [ ] The audience condition that narrowed it to you has been removed or broadened.
* [ ] **Frequency Limits** are set. At least one cap per device per time window.
* [ ] The deeplink URL or review-prompt behavior is what you expect.
* [ ] Someone else on the team knows the campaign is going live.

## Related

* [Managing deeplinks](/user-guide/managing-deeplinks.md) — testing deeplink campaigns specifically.
* [Rate & Review flows](/user-guide/rate-review-flows.md) — testing native review prompts.
* [Custom popups](/user-guide/custom-popups.md) — testing popup content.
* [Testing your integration](/developer-guide/testing-your-integration.md) — the engineer-side checklist.
