trucking: same-day expiring coupon to drive immediate conversion

The sales we got came at $79 + a 24hr coupon; cutting MCS-150 to $39 flat
removed urgency and conversions did NOT improve (a permanent low price sets a
new anchor and lets people defer). Restore the higher anchor and let an
expiring discount create the now-or-lose-it decision.

- Restore MCS-150 anchor $39 -> $79 (catalog single source + regenerated).
- build_trucking_campaigns.py: mint ONE random 5-letter coupon per send-day
  (40% off, valid through 23:59:59 ET that day) into the existing discount_codes
  table; inject coupon_code/pct/expires + a ?code= LP link into every email.
  Idempotent per day; service-fee-only scope (gov/pass-through fees never cut).
- Listmonk MCS-150 (186) + Inactive USDOT (188) templates: lead with the
  struck-through anchor + sale price + code + 'expires tonight', and point the
  primary CTA at the order page (with code) instead of the 'free check' tool.
- OrderPriceBanner: validates ?code= via /api/v1/discount and shows
  was/now + expiry; Wizard forwards the code to order creation.
- Verified: code gen, expiry math, scope enforcement, discount API
  (40% off $79 = $47.40), site+api builds clean.
This commit is contained in:
justin 2026-06-13 20:43:47 -05:00
parent dd4ed3ea38
commit 5e9aec40d1
30 changed files with 216 additions and 31 deletions

View file

@ -5,17 +5,29 @@ export interface Props {
priceCents?: number;
govFeeLabel?: string;
note?: string;
serviceSlug?: string;
}
const { priceCents, govFeeLabel, note } = Astro.props;
const { priceCents, govFeeLabel, note, serviceSlug } = Astro.props;
const hasPrice = typeof priceCents === "number";
const API = import.meta.env.PUBLIC_API_URL || "";
---
{hasPrice && (
<aside class="pw-price-banner" aria-label="Service price">
<aside
class="pw-price-banner"
aria-label="Service price"
data-price-cents={priceCents}
data-service-slug={serviceSlug || ""}
data-api={API}
>
<div>
<p class="pw-price-label">Service fee</p>
<p class="pw-price-value">{formatUSD(priceCents!)}</p>
<p class="pw-price-value">
<span class="pw-price-anchor" hidden></span>
<span class="pw-price-now">{formatUSD(priceCents!)}</span>
</p>
<p class="pw-price-deal" hidden></p>
</div>
<div class="pw-price-copy">
{govFeeLabel ? (
@ -28,6 +40,46 @@ const hasPrice = typeof priceCents === "number";
</aside>
)}
<script>
// Same-day campaign coupon: if the visitor arrived via ?code=XXXXX, validate
// it and surface the deal (struck-through anchor + discounted price + expiry).
// The discount applies to the service fee only; pass-through fees are unaffected.
(async () => {
const banner = document.querySelector<HTMLElement>(".pw-price-banner");
if (!banner) return;
const code = (new URLSearchParams(location.search).get("code") || "").toUpperCase().trim();
if (!code) return;
const priceCents = parseInt(banner.dataset.priceCents || "0", 10);
const slug = banner.dataset.serviceSlug || "";
const api = banner.dataset.api || "";
if (!priceCents) return;
try {
const url = `${api}/api/v1/discount/${encodeURIComponent(code)}`
+ `?amount=${priceCents}${slug ? `&service=${encodeURIComponent(slug)}` : ""}`;
const r = await fetch(url);
if (!r.ok) return;
const d = await r.json();
if (!d || !d.valid || !d.discount_cents) return;
const now = priceCents - d.discount_cents;
const fmt = (c: number) => `$${(c / 100).toFixed(c % 100 === 0 ? 0 : 2)}`;
const anchor = banner.querySelector<HTMLElement>(".pw-price-anchor");
const nowEl = banner.querySelector<HTMLElement>(".pw-price-now");
const deal = banner.querySelector<HTMLElement>(".pw-price-deal");
if (anchor) { anchor.textContent = fmt(priceCents); anchor.hidden = false; }
if (nowEl) nowEl.textContent = fmt(now);
if (deal) {
const pct = d.discount_type === "percent" ? `${d.discount_value}% off` : `${fmt(d.discount_cents)} off`;
deal.innerHTML = `<strong>${pct}</strong> with code <strong>${code}</strong> &middot; expires 11:59 PM ET tonight`;
deal.hidden = false;
}
} catch { /* no-op: fall back to full price */ }
})();
</script>
<style>
.pw-price-banner {
display: flex;
@ -56,6 +108,19 @@ const hasPrice = typeof priceCents === "number";
line-height: 1;
font-weight: 900;
}
.pw-price-anchor {
color: #9ca3af;
font-weight: 700;
text-decoration: line-through;
font-size: 0.55em;
margin-right: 0.4em;
}
.pw-price-deal {
margin: 0.45rem 0 0;
color: #b91c1c;
font-size: 0.85rem;
font-weight: 700;
}
.pw-price-copy {
max-width: 30rem;
color: #475569;

View file

@ -639,6 +639,10 @@ const STEP_LABELS: Record<string, string> = {
customer_name: name,
customer_phone: d.phone || "",
intake_data: state.intake_data,
// Same-day promo code from the campaign email link (?code=XXXXX).
// The server validates it (expiry + scope) and discounts the
// service fee only -- government/pass-through fees are never reduced.
discount_code: (new URLSearchParams(window.location.search).get("code") || "").toUpperCase().trim() || undefined,
}),
});
if (!createResp.ok) {