From 3328f30a063a0d9606753dab69e09a20872f1d29 Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 25 Jul 2026 14:08:52 +0000 Subject: [PATCH] Add /newsletter-confirmed double-opt-in confirmation page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Brevo's redirectionUrl now points here instead of the homepage — a static page matching /bestellbestaetigung's visual language (brand- tinted checkmark circle, serif display heading, thin brand divider). No query params to read; Brevo's confirmation redirect carries nothing this page needs. Co-Authored-By: Claude Sonnet 5 --- README.md | 12 ++++-- app/lib/brevo.ts | 5 +-- app/newsletter-confirmed/page.tsx | 66 +++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 app/newsletter-confirmed/page.tsx diff --git a/README.md b/README.md index af45095..e4a6cc9 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ independent, see the "Monitoring & alerting" section). `STRIPE_SECRET_KEY`, (Stripe)" below. `BREVO_API_KEY`, `BREVO_LIST_ID`, `BREVO_DOUBLE_OPTIN_TEMPLATE_ID` (no safe default — required for newsletter signups to trigger a confirmation email at all), -`BREVO_DOI_REDIRECT_URL` (optional, defaults to the homepage) — see +`BREVO_DOI_REDIRECT_URL` (optional, defaults to `/newsletter-confirmed`) — see "Newsletter signup" below. Set in Coolify's app settings for production, not in a committed `.env`. @@ -1074,9 +1074,13 @@ unsynced. (`POST /v3/contacts/attributes/normal/OPT_IN_SOURCE`) or Brevo silently drops it on every request (no error at all, just never stored) rather than rejecting the request. `redirectionUrl` (where Brevo sends the - contact after they click confirm) defaults to the homepage via - `BREVO_DOI_REDIRECT_URL` — no dedicated "danke, bestätigt" landing page - exists yet. + contact after they click confirm) defaults to `/newsletter-confirmed` + via `BREVO_DOI_REDIRECT_URL` — a static confirmation page + (`app/newsletter-confirmed/page.tsx`), same visual language as + `/bestellbestaetigung` (brand-tinted circular checkmark, serif display + heading, thin brand divider). No query params to read — Brevo's + redirect carries nothing this page needs, unlike `/checkout/verarbeitung` + which polls actual payment status. - **`app/lib/useNewsletterSignup.ts`** — the shared email/consent/submit state + on-blur validation + refocus-on-invalid-submit behind all four forms (same "state of the art, simple" input-quality bar as checkout's diff --git a/app/lib/brevo.ts b/app/lib/brevo.ts index b15244a..51c175a 100644 --- a/app/lib/brevo.ts +++ b/app/lib/brevo.ts @@ -33,10 +33,7 @@ export async function upsertNewsletterContact( if (!apiKey || !listId || !templateId) { return { ok: false, reason: "BREVO_API_KEY/BREVO_LIST_ID/BREVO_DOUBLE_OPTIN_TEMPLATE_ID nicht konfiguriert." }; } - // No dedicated "danke, bestätigt" landing page exists yet — falls back - // to the homepage rather than blocking double opt-in on that page - // existing first. Revisit once one exists. - const redirectionUrl = process.env.BREVO_DOI_REDIRECT_URL || "https://einfach-produktiv.mk360.de/"; + const redirectionUrl = process.env.BREVO_DOI_REDIRECT_URL || "https://einfach-produktiv.mk360.de/newsletter-confirmed"; try { const res = await fetch(BREVO_DOUBLE_OPTIN_URL, { diff --git a/app/newsletter-confirmed/page.tsx b/app/newsletter-confirmed/page.tsx new file mode 100644 index 0000000..286fec3 --- /dev/null +++ b/app/newsletter-confirmed/page.tsx @@ -0,0 +1,66 @@ +import type { Metadata } from "next"; +import Link from "next/link"; +import { Reveal } from "../components/Reveal"; +import { Footer } from "../components/Footer"; +import { TrustRow } from "../components/TrustRow"; + +// robots: noindex — transactional landing page (Brevo's double opt-in +// redirectionUrl target, see app/lib/brevo.ts's BREVO_DOI_REDIRECT_URL), +// same reasoning as /bestellbestaetigung and /checkout: nothing here is +// meant to be found via search, only reached via the confirmation link. +export const metadata: Metadata = { + title: "Newsletter bestätigt", + description: "Deine Newsletter-Anmeldung bei einfach produktiv ist bestätigt.", + robots: { + index: false, + follow: true, + }, +}; + +// Static — Brevo's confirmation click lands here with no query params to +// read, so unlike /bestellbestaetigung (which hydrates a sessionStorage +// order snapshot) or /checkout/verarbeitung (which polls payment status), +// this page has nothing to fetch or wait on. Same visual language as +// those two: warm bg-bg-base, brand-tinted circular icon, serif display +// heading, thin brand divider — see BestellbestaetigungContent.tsx for +// the pattern this mirrors. +export default function NewsletterConfirmedPage() { + return ( + <> +
+ +
+ +
+

+ Bestätigt! +

+

+ Du bist jetzt Teil unseres Newsletters. +

+
+

+ Schön, dass du dabei bist! Ab jetzt bekommst du hin und wieder Impulse, neue Produkte + und kleine Erinnerungen von uns, damit dein Alltag ein bisschen leichter wird. +

+ + Jetzt stöbern + + + +
+