Stu Mason
Stu Mason

Activity

StuMason/cleanconnect
TidyLinker.com
TypeScript
Pull Request Opened

PR #144 opened: fix: throttle Resend API + consent-gated Meta Pixel

Summary

Two unrelated weekend issues bundled (both small, both client-facing):

  • Resend rate limit fixed. All bulk-sendable Mailables now share a Redis-backed resend-api rate limiter (4/sec, leaving headroom under Resend's 5/sec cap). Cluster-wide enforcement across the 10 production Horizon workers, so email:send-launch-announcement, admin bulk nudges, and concurrent transactional sends no longer trip Too many requests. Rate-limited jobs are released back to the queue with delay — no mail lost.
  • Meta (Facebook) Pixel installed, consent-gated. Loads only after the visitor accepts marketing cookies via the existing consent banner. Pixel ID is wired through VITE_FACEBOOK_PIXEL_ID; if unset the component is a no-op (so dev/local builds never load it). Fires PageView on initial load and on every Inertia navigation.

To get visitors the updated marketing description (which now names Meta and the data flow) the consent storage key was bumped to cookie-consent-v2 — existing visitors will see the banner once more.

Required prod env change

Set in Coolify and redeploy (Vite injects at build time):

VITE_FACEBOOK_PIXEL_ID=1008517204941231

Until that's set + a fresh build ships, the Pixel is a no-op even for visitors who consent.

Test plan

  • php artisan test --compact tests/Feature/Mail — the new throttle test covers all 5 mailables and asserts the limiter is registered.
  • Existing tests/Feature/SendLaunchAnnouncementTest.php and tests/Feature/Admin/NudgeControllerTest.php still pass.
  • Manually: visit prod after deploy, confirm consent banner re-appears, refuse marketing → Pixel does not load (no fbevents.js request, no _fbp cookie). Accept marketing → Pixel loads and fires PageView.
  • Manually: trigger a bulk launch announcement / bulk nudge from admin and confirm Resend no longer logs Too many requests in Sentry.

Files

  • app/Providers/AppServiceProvider.php — register resend-api rate limiter (4/sec)
  • app/Mail/Concerns/ThrottlesResendApi.php — trait returning [new RateLimitedWithRedis('resend-api')] from middleware()
  • app/Mail/{LaunchAnnouncement,OnboardingNudge,ProfileCompletionNudge,StripeSetupReminder,VerificationReminder}Mail.php — apply trait
  • tests/Feature/Mail/ThrottlesResendApiTest.php — wiring tests
  • resources/js/components/meta-pixel.tsx — new client component, consent-gated
  • resources/js/components/cookie-consent-banner.tsx — bump storage key to v2, dispatch cookie-consent-changed event on save
  • resources/js/components/cookie-preferences-modal.tsx — plain-English marketing description naming Meta and the data flow
  • resources/js/app.tsx — render <MetaPixel /> inside the consent provider
  • .env.example — document VITE_FACEBOOK_PIXEL_ID
+187
additions
-9
deletions
13
files changed