0059: Introduce Draft Iterations to AdSuite
STATUS
Accepted
CONTEXT
The next phase of AdSuite is integrating with Tune to automate campaign setup.
Previously, there was not a way to save an iteration with out publishing and setting it as the active iteration. With the upcoming Tune integration, publishing an iteration will trigger API calls to update the corresponding offer in Tune. This means we need users to be able to build out an iteration without those API calls firing until they're ready. A draft state is a prerequisite for that integration.
Beyond the Tune requirement, enforcing a draft-to-publish workflow also prevents unfinished iterations from accidentally going into production and gives users a space to plan changes before committing them.
Considered Options
Option 1 — No draft iterations
Keep the existing behavior where creating an iteration immediately makes it active. Tune API calls would fire on creation, requiring iterations to be fully configured before being created. Would force users to change behavior when moving from the CPE sheet where they currently draft and return to iterations before going live.
Option 2 — Draft iterations with manual active selection
Introduce draft iterations and allow users to manually select which iteration is active, including reactivating previously archived iterations.
Option 3 — Draft iterations with publish-only activation (chosen)
Introduce draft iterations where the only way to set an iteration as active is through an explicit publish action. Old iterations cannot be reactivated — only new drafts can be published.
DECISION
We chose Option 3 — draft iterations with publish-only activation. Users can create and edit draft iterations without affecting production. Publishing a draft activates it and automatically archives the previously active iteration in a single database transaction.
Key implementation details:
- A
published_attimestamp column is added to iterations. Draft status is determined bypublished_atbeing null. - Three iteration states: Draft (
published_at = null), Active (published_at != null && is_active = true), Archived (published_at != null && is_active = false). - Validation is only enforced on publish, not on draft saves, so users can save incomplete work.
- Published iterations are immutable — editing is disabled in the UI and direct URL access is redirected.
- The publish action is wrapped in a DB transaction (deactivate old + activate new) to prevent inconsistent state.
CONSEQUENCES
Positive
- Users can plan and iterate on campaigns at their own pace without relying on external tools like the CPE sheet.
- Published iterations are immutable, preventing accidental modifications to live campaigns.
- The publish action provides a clear integration point for the upcoming Tune API calls.
Negative
- Users cannot reactivate a previously archived iteration. To restore an old configuration, they must copy it into a new draft, which resets conversion stats and starts tracking from scratch.
Risks and Mitigations
| Risk | Mitigation |
|---|---|
| Accidental publish — Publishing is irreversible and will trigger Tune API calls once the integration is live. | Validation enforces all required fields are complete before a publish can succeed. |
| Orphaned drafts — Users may create drafts and never publish them, leading to clutter over time. | Low immediate risk. Can be addressed later with a cleanup policy or UI filtering if it becomes a problem. |
| Tune API failure on publish — Once Tune integration is added, a failed API call during publish could leave the system in an inconsistent state. | The publish DB transaction is scoped to AdSuite state only. Tune integration will need its own error handling and rollback strategy, to be defined in a separate ADR. |
| Loss of historical stats on copy — Copying an archived iteration to create a new draft does not carry over conversion stats. | This is a known tradeoff. Users should be informed in the UI that copying starts a fresh iteration for tracking purposes. Future adsuite iterations could allow for users to view statistical data on grouped iterations. |
NOTES
- This is a post-implementation ADR documenting a decision that has already been built and deployed.
- The Tune integration will be covered in a separate ADR. Draft iterations are a prerequisite but do not themselves include any Tune API logic.
References
- Draft Iterations ticket breakdown canvas
- Goal & Event Mapping in AdSuite canvas
- Slack context: Draft iterations needed before Tune integration
- Linear project: Draft Iterations
- PR #129: docs(ADR): Introduce Draft Iterations to AdSuite
- PR #180: fix(adr): strip literal [Number] from ADR filenames and sidebar
Original Author
Emma Worthington
Approval date
N/A — post-implementation ADR
Approved by
N/A — post-implementation ADR
Appendix
N/A