diff --git a/src/app/globals.css b/src/app/globals.css index 0192bb9a..0c96f3bb 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -111,8 +111,6 @@ } /* CrawlProof ad unit: zero height until ad.js starts a fill, so an unsold or - blocked slot leaves no hole. Reserves the format plus ad.js's caption. */ + blocked slot leaves no hole. Low profile: one thin text_link line. */ .cp-ad { height: 0; overflow: hidden; } -.cp-ad[data-cp-filled] { height: auto; overflow: visible; margin: 2rem 0; } -.cp-ad[data-cp-filled][data-format="banner_728x90"] { min-height: 106px; } -.cp-ad[data-cp-filled][data-format="banner_300x250"] { min-height: 266px; } +.cp-ad[data-cp-filled] { height: auto; overflow: visible; margin: 0.5rem 0; } diff --git a/src/components/ad-unit.tsx b/src/components/ad-unit.tsx index 048d5642..77ec6395 100644 --- a/src/components/ad-unit.tsx +++ b/src/components/ad-unit.tsx @@ -1,48 +1,38 @@ "use client"; -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import { usePathname } from "next/navigation"; -import { AD_SLOT, isAdPage, requestAdScan, type AdFormat } from "@/lib/ads"; - -/** 728x90 needs the full content column; narrower viewports get the 300x250. */ -const LEADERBOARD_QUERY = "(min-width: 768px)"; +import { AD_SLOT, isAdPage, requestAdScan } from "@/lib/ads"; /** - * One CrawlProof unit at the top of the main content on smshub.dev public pages - * (never above or inside the footer). + * One low-profile CrawlProof text_link unit at the top of the main content on + * smshub.dev public pages (never the homepage, never above or inside the footer). * - * The div is rendered without `data-slot`, so ad.js's own first pass skips it; - * the mount effect picks one format from the viewport, sets slot + format and - * asks for a scan. Exactly one fill, never a hidden twin. The wrapper collapses - * to nothing until ad.js marks the unit `data-cp-filled` (see globals.css). + * The wrapper collapses to nothing until ad.js marks the unit `data-cp-filled` + * (see globals.css). The mount effect asks ad.js to rescan, since client + * navigation mounts the unit after ad.js's first pass. */ export function AdUnit() { const pathname = usePathname(); const show = isAdPage(pathname); - const [format, setFormat] = useState(null); useEffect(() => { if (!show) return; - setFormat(window.matchMedia(LEADERBOARD_QUERY).matches ? "banner_728x90" : "banner_300x250"); - }, [show]); - - useEffect(() => { - if (!show || !format) return; return requestAdScan(); - }, [show, format, pathname]); + }, [show, pathname]); if (!show) return null; return ( -
+
); diff --git a/src/lib/__tests__/ads.test.ts b/src/lib/__tests__/ads.test.ts index 0d3bb346..87c1929e 100644 --- a/src/lib/__tests__/ads.test.ts +++ b/src/lib/__tests__/ads.test.ts @@ -3,12 +3,12 @@ import { isAdPage } from "../ads"; describe("isAdPage", () => { it("shows on public pages", () => { - for (const p of ["/", "/docs", "/docs/telnyx", "/privacy", "/terms/", "/sms", "/phonenumbers"]) { + for (const p of ["/docs", "/docs/telnyx", "/privacy", "/terms/", "/sms", "/phonenumbers"]) { expect(isAdPage(p)).toBe(true); } }); - it("never shows in the app, auth or checkout", () => { - for (const p of ["/inbox", "/numbers", "/settings", "/login", "/register", "/org/x", "/docsx", null]) { + it("never shows on the homepage, in the app, auth or checkout", () => { + for (const p of ["/", "/inbox", "/numbers", "/settings", "/login", "/register", "/org/x", "/docsx", null]) { expect(isAdPage(p)).toBe(false); } }); diff --git a/src/lib/ads.ts b/src/lib/ads.ts index 0d534f50..582c28b5 100644 --- a/src/lib/ads.ts +++ b/src/lib/ads.ts @@ -16,10 +16,10 @@ export const AD_HEIGHTS: Record = { }; /** - * Public marketing/docs pages that carry the unit. Everything else (inbox, - * numbers, settings, auth, checkout) stays ad-free. + * Public marketing/docs pages that carry the unit. The homepage and everything + * else (inbox, numbers, settings, auth, checkout) stays ad-free. */ -const AD_EXACT = new Set(["/", "/privacy", "/terms", "/sms", "/install", "/phonenumbers", "/verification-numbers"]); +const AD_EXACT = new Set(["/privacy", "/terms", "/sms", "/install", "/phonenumbers", "/verification-numbers"]); const AD_PREFIXES = ["/docs"]; export function isAdPage(pathname: string | null | undefined): boolean {