Skip to content

42 — TestimonialCampaign Model & Automation Rules (Blueprint §5.2)

Cursor-ready plan for implementing the core campaign model, activation rules, scheduling semantics, and pipeline contracts.

42 — TestimonialCampaign Model & Automation Rules (Blueprint §5.2)

Section titled “42 — TestimonialCampaign Model & Automation Rules (Blueprint §5.2)”

Source: 02-Implementation-Blueprint.md§5.2 New model: TestimonialCampaign.

This document is a build spec only. No code changes are implied until a task references this file.

Related: 17 (campaign list), 18 (campaign create/edit), 41 (campaign-product mapping), 07 (request pipeline), 39 (request lifecycle), 20 (schema).


Implement TestimonialCampaign as the authoritative automation policy object that controls trigger, targeting mode, channel, reminder behavior, and incentives for outbound testimonial requests.


Blueprint §5.2 fields:

  • id
  • shopId
  • name
  • status (active|paused|archived)
  • triggerEvent (order_paid|order_fulfilled)
  • delayDays
  • channel (email|sms|both)
  • allProducts
  • reminderEnabled
  • reminderDelayDays
  • maxReminders
  • incentiveEnabled
  • incentiveType (discount_code|gift_card)
  • incentiveValue
  • timestamps

Index:

  • @@index([shopId, status])

  • model + migration
  • validation and activation constraints
  • runtime interpretation by request pipeline
  • campaign status lifecycle and safe transitions
  • A/B testing variants per campaign
  • multi-trigger campaign orchestration
  • campaign-level analytics rollups beyond existing screens

A campaign is:

  • a shop-scoped rule set
  • deciding when to send (triggerEvent, delayDays)
  • deciding who to send to (allProducts + mapping table)
  • deciding how to send (channel, templates)
  • deciding follow-up behavior (reminder*)
  • optionally attaching incentive messaging context

This model should not directly store request execution state (that belongs to TestimonialRequest).


Allowed statuses:

  • active
  • paused
  • archived

Transition rules:

  • active <-> paused
  • active|paused -> archived
  • archived is terminal by default (restore optional future action)

Runtime contract:

  • pipeline selects only status='active'.

  • name required, trimmed
  • triggerEvent in allowed enum
  • delayDays integer between 0 and 60
  • channel in allowed enum
  • if allProducts=true -> no required product mappings
  • if allProducts=false -> require at least one target in mapping table (41) or equivalent collection mapping
  • if reminderEnabled=false:
    • maxReminders should be 0 (or ignored by pipeline; choose one behavior)
  • if enabled:
    • reminderDelayDays >= 1
    • maxReminders within safe bounds (recommend 1..3 v1)
  • if incentiveEnabled=false:
    • clear or ignore incentiveType, incentiveValue
  • if enabled:
    • require valid incentiveType
    • require non-empty incentiveValue

Before setting status to active, ensure:

  1. audience is valid
  2. required templates resolve for selected channel and reminder stages
  3. schedule fields valid

If guardrail fails:

  • block activation with actionable error details.

This prevents runtime failures in send worker.


Sender/request planner should consume campaign as read-only input:

  • triggerEvent -> webhook match
  • delayDays -> scheduledFor
  • channel -> template/provider path
  • reminder fields -> reminder scheduler
  • incentive fields -> {{incentive_text}} rendering context

Do not mutate campaign row during request processing except optional operational fields (lastSentAt if adopted).


Section titled “8) Optional operational fields (recommended)”

Not in blueprint but practical:

  • lastSentAt DateTime?
  • lastErrorAt DateTime?
  • lastErrorSummary String?

These improve campaign list diagnostics without scanning all requests.

If added, keep them nullable and non-blocking.


  • filter by shopId
  • status/channel/trigger filters
  • sort by updatedAt or lastSentAt
  • fetch active campaigns for shop + trigger
  • prefetch targeting mappings in batch

Campaigns contain no direct customer PII.

On shop redact:

  • campaigns should delete via shop cascade.

Archived campaigns may be retained for merchant audit/history unless explicit delete action is introduced.


  • Campaign create/update persists all blueprint fields correctly.
  • Invalid configs are blocked by server validation.
  • Activation guardrails prevent broken active campaigns.
  • Pipeline includes only active campaigns.
  • Archive state removes campaign from runtime selection.

12) Suggested implementation order (for Cursor)

Section titled “12) Suggested implementation order (for Cursor)”
  1. Add Prisma model + migration.
  2. Add shared validation schema/constants for campaign fields.
  3. Implement create/edit actions with status transition logic.
  4. Add activation guardrails (template + targeting checks).
  5. Wire request pipeline to consume campaign fields.

  • 02-Implementation-Blueprint.md — §5.2
  • 18-campaign-create-edit-screen-3.md
  • 17-campaigns-list-screen-2.md
  • 41-testimonial-campaign-product-model-blueprint-section-5-3.md
  • 07-email-sms-request-delivery-pipeline.md

This folder already includes 05 through 41 plans. This file is 42-....