docs: trucking state-campaign send runbook
Ties the prioritized marketing-send plan (NY HUT -> CT HUF -> D&A -> New Carrier Startup -> CA MCP) to the existing Listmonk builders (setup_trucking_campaigns.py creates the drafts + tests; populate_new_carrier_startup_campaign.py builds the data-targeted New Carrier audience). Draft/populate/test steps are safe and idempotent; starting a bulk send is flagged as an irreversible operator-only step. Cross-references the new fulfillment_status machine and the authorization e-sign so campaign expectations match fulfillment.
This commit is contained in:
parent
29ad0908ee
commit
058d7cfbfe
1 changed files with 96 additions and 0 deletions
96
docs/trucking-state-campaign-send-runbook.md
Normal file
96
docs/trucking-state-campaign-send-runbook.md
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Trucking State-Campaign Send Runbook
|
||||||
|
|
||||||
|
Companion to `trucking-marketing-send-plan.md`. The plan ranks the sends; this
|
||||||
|
runbook is the exact, repeatable procedure to launch them. Everything up to the
|
||||||
|
final "start the send" step is safe and idempotent. **Starting a bulk send is
|
||||||
|
irreversible** and is the only step that should be run deliberately by an
|
||||||
|
operator.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- `DATABASE_URL` pointing at production Postgres (FMCSA census + compliance_orders).
|
||||||
|
- `LISTMONK_URL`, `LISTMONK_USER`, `LISTMONK_PASS` for the Listmonk instance.
|
||||||
|
- Migrations applied through at least `083_fmcsa_campaign_tracking.sql`
|
||||||
|
(`listmonk_campaign_type`, `listmonk_sent_at`) and, for fulfillment status,
|
||||||
|
`086_state_trucking_fulfillment_status.sql`.
|
||||||
|
|
||||||
|
## Prioritized send order
|
||||||
|
|
||||||
|
Lowest fulfillment friction first (see the plan for the rationale):
|
||||||
|
|
||||||
|
1. **NY HUT setup** — clean tax-pro authorization (E-ZRep / TR-2000).
|
||||||
|
2. **CT Highway Use Fee** — electronic via myconneCT, CSV vehicle import.
|
||||||
|
3. **DOT Drug & Alcohol Program** — no state portal; recurring.
|
||||||
|
4. **New Carrier Startup Bundle** — broad cross-sell; data-targeted.
|
||||||
|
5. **CA MCP + CARB** — medium friction (portal + insurance coordination).
|
||||||
|
|
||||||
|
## Step 1 — Build/refresh the audience lists
|
||||||
|
|
||||||
|
The draft campaigns and their lists are created by:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
LISTMONK_URL=… LISTMONK_USER=api LISTMONK_PASS=… \
|
||||||
|
python3 scripts/setup_trucking_campaigns.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This is **safe**: it creates draft campaigns (NY HUT, CT HUF, D&A, CA MCP, New
|
||||||
|
Carrier Startup, hazmat) and sends a single test to `CAMPAIGN_TEST_EMAIL`. It
|
||||||
|
does not start any bulk send.
|
||||||
|
|
||||||
|
For the New Carrier Startup list specifically, populate it with the
|
||||||
|
data-targeted, billed-at-cost-aware audience (carriers with usable email, recent
|
||||||
|
FMCSA `add_date`, small fleet, and no paid Performance West startup order):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Preview first — read-only, prints sample candidates and a count.
|
||||||
|
DATABASE_URL=… python3 scripts/populate_new_carrier_startup_campaign.py --dry-run
|
||||||
|
|
||||||
|
# Then import (does NOT mark listmonk_sent_at; adding to a list != sending).
|
||||||
|
DATABASE_URL=… LISTMONK_URL=… LISTMONK_PASS=… \
|
||||||
|
python3 scripts/populate_new_carrier_startup_campaign.py --limit 500 --recent-days 180
|
||||||
|
```
|
||||||
|
|
||||||
|
Subscriber attributes set: `company`, `dot_number`, `state`, `city`, `trucks`,
|
||||||
|
`drivers`, `add_date`, `missing_items_html`, `startup_score`.
|
||||||
|
|
||||||
|
State lists (NY/CT/CA) are populated from the FMCSA census by base/operating
|
||||||
|
state. Use the state-segment tooling to attach carriers by `phy_state` /
|
||||||
|
operating-state to each list before sending.
|
||||||
|
|
||||||
|
## Step 2 — Review the draft + test send
|
||||||
|
|
||||||
|
In Listmonk, open each draft campaign and:
|
||||||
|
|
||||||
|
- confirm the subject and `missing_items_html` / company merge tags render;
|
||||||
|
- confirm the list count is the audience you expect;
|
||||||
|
- confirm the test email looks correct in a real inbox (rendering, links, CTA).
|
||||||
|
|
||||||
|
## Step 3 — Start the send (operator action, irreversible)
|
||||||
|
|
||||||
|
Send one campaign at a time, in the priority order above, and watch
|
||||||
|
deliverability/bounces before starting the next. In Listmonk, set the campaign
|
||||||
|
status to `running` (or `scheduled` with a send time).
|
||||||
|
|
||||||
|
For the scheduled MCS-150 / inactive-USDOT regional sends, the nightly builder
|
||||||
|
`build_trucking_campaigns.py` already schedules per timezone; the state campaigns
|
||||||
|
here are launched manually so each can be paced.
|
||||||
|
|
||||||
|
After a state campaign sends, record campaign-type-specific tracking
|
||||||
|
(`listmonk_campaign_type`) rather than the global `listmonk_sent_at`, so an
|
||||||
|
unrelated future campaign to the same carrier is not blocked.
|
||||||
|
|
||||||
|
## Fulfillment expectation set at send time
|
||||||
|
|
||||||
|
Every state-filing campaign points at a paid service whose fulfillment now
|
||||||
|
follows the `compliance_orders.fulfillment_status` machine (migration 086):
|
||||||
|
|
||||||
|
```
|
||||||
|
authorization_required -> authorization_signed -> awaiting_customer_delegation
|
||||||
|
-> awaiting_secure_credentials -> awaiting_government_fee_approval
|
||||||
|
-> awaiting_insurance_filing -> ready_to_file -> filed_waiting_state -> completed
|
||||||
|
```
|
||||||
|
|
||||||
|
The first customer touch after purchase is the **Limited Authorization to File**
|
||||||
|
e-sign (the signature is stamped exactly on the form's signature line), so the
|
||||||
|
campaign copy and order pages already disclose the authorization step and the
|
||||||
|
billed-at-cost government fees.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue