Skip to content

feat(growth): one-click pack buy links in the credit alert emails (GROWTH_50 #7) - #110

Merged
Deesmo merged 1 commit into
mainfrom
growth50-email-buy-links
Jul 31, 2026
Merged

feat(growth): one-click pack buy links in the credit alert emails (GROWTH_50 #7)#110
Deesmo merged 1 commit into
mainfrom
growth50-email-buy-links

Conversation

@Deesmo

@Deesmo Deesmo commented Jul 31, 2026

Copy link
Copy Markdown
Owner

What

GROWTH_50 item #7 (council-cleared, Brad GO 2026-07-31): prominent, working one-click buy links in BOTH credit emails — the low-credit alert (sendLowCreditAlert) and the out-of-credits alert (sendCreditsDepletedAlert).

How

  • Every pack card is now itself a one-click link to the PR feat(funnel): purchase-intent preservation, pack preselect links, dashboard upsell states #100 GET deep-link https://archtools.dev/pricing?pack=<starter|pro|business> (verified against the pricing.html preselect allowlist at lines 346–348 — exactly those three ids). The page only highlights + scrolls; checkout never auto-fires from a GET (council rule, already pinned by intent-funnel.test.mjs).
  • CTA button moved above the fold in the low-credit email ("Buy credits now →"); depleted email keeps its button and gains the clickable pack cards (its old "Option 1" card was inert text).
  • Plaintext alternative added to both emails (they previously sent HTML-only) so the buy links work in text-only clients; the send wrappers now pass text through.
  • Pack copy rendered from lib/creditPacks.RECOMMENDABLE_PACKS instead of hardcoded credit/price strings (same catalog the 402 funnel uses; sizes pinned by the intent-funnel drift guard). No pricing amounts changed — scripts/check-price-drift.mjs untouched and passing.
  • Render logic exported (renderLowCreditAlert / renderCreditsDepletedAlert) following the existing renderVerificationEmail "exported for render tests" pattern. Subjects, styling (layout() + .stat/.btn classes), and the AuditLog once-per-cycle dedup in utils/credits.ts are all unchanged.

Tests

  • New api/tests/credit-email-buylinks.test.mjs (28 checks, mirrors reactivation-render.test.mjs): per-pack links present in html and text of both emails; prominent CTA href; no /v1/billing/checkout/subscribe API URL ever appears in an email (auto-fire guard); every linked pack id is in the pricing.html ?pack= allowlist + has a buy button (drift guard); agent id truncation; wrapper text pass-through and alert wiring source pins. Added to the npm test chain.
  • intent-funnel.test.mjs email pin updated to the new packHref helper (was a literal-string count that the refactor made stale).

Verification (all run locally in the worktree)

  • npx prisma generate && npx tsc --noEmit → clean (exit 0)
  • node tests/credit-email-buylinks.test.mjs → 28/28 ✓
  • node tests/intent-funnel.test.mjs, tests/credit-alert-dedup.test.mjs, tests/reactivation-render.test.mjs → all pass
  • node api/tests/integration.test.js (13/13) + node api/tests/pages.test.js (31/31) — the CI suites
  • node scripts/check-price-drift.mjs → OK

No dist/node_modules churn committed (4 source/test files only).

🤖 Generated with Claude Code


Note

Low Risk
Transactional email content and growth funnel links only; no billing API or credit-deduction logic changes, with tests enforcing no checkout URLs in email bodies.

Overview
Low-credit and credits-depleted emails now drive users to purchase with clickable pack deep-links (/pricing?pack=<id>) built from RECOMMENDABLE_PACKS, instead of static pack copy and a single generic pricing link.

Each recommendable pack is a one-click link in HTML (pack cards are <a> tags) and in a new plaintext body for both alerts; send wrappers pass text through to sendEmail. Render logic is split into exported renderLowCreditAlert / renderCreditsDepletedAlert (same pattern as verification email tests). The depleted email still promotes x402; layout, subjects, and utils/credits.ts alert dedup wiring are unchanged.

Tests: new credit-email-buylinks.test.mjs (links, catalog drift, no checkout API URLs in email, wiring pins) added to npm test; intent-funnel.test.mjs pins the packHref helper instead of counting literal starter URLs.

Reviewed by Cursor Bugbot for commit c295ffd. Configure here.

…OWTH_50 #7)

Low-credit + credits-depleted emails now carry working one-click buy
links: every pack card is itself a GET deep-link to the pre-selected
pricing page (/pricing?pack=starter|pro|business — the PR #100 preselect
surface; page only highlights/scrolls, checkout never auto-fires per the
council rule), the CTA button is moved above the fold, and both emails
gain a plaintext alternative so the buy link works in text-only clients.

Pack copy is now rendered FROM lib/creditPacks.RECOMMENDABLE_PACKS
instead of hardcoded strings, and the render functions are exported for
render tests (renderVerificationEmail pattern). Subjects and the
AuditLog once-per-cycle dedup wiring in utils/credits.ts are unchanged.

Tests: new credit-email-buylinks.test.mjs (28 checks: per-pack links in
html+text, prominent CTA, no checkout/subscribe API URL in any email,
pricing.html ?pack= allowlist drift guard, wrapper text pass-through,
alert wiring pins); intent-funnel email pin updated to the new helper.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@Deesmo
Deesmo merged commit 99a06f4 into main Jul 31, 2026
7 checks passed
@Deesmo
Deesmo deleted the growth50-email-buy-links branch July 31, 2026 16:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant