From ed764b1bbe955fca660c344d56c3e1245d9b6286 Mon Sep 17 00:00:00 2001 From: Ryan Salazar Date: Thu, 28 May 2026 02:07:06 +0000 Subject: [PATCH] ads: route all clicks through advertising.RMP.com/r/ + cache-aware banner reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two compounding bugs caused 0 clicks since May 22: 1. lib/ads.ts exported ADS_728X90 / ADS_300X250 / FIXED_300X600 as IIFE-evaluated module constants. They captured the FALLBACK array at module-load time, before the centralized RMP banner cache populates. Every render that referenced them got FALLBACK banners whose click_url was the direct advertiser URL — bypassing the centralized click logger entirely. 300x250s escaped because every page reads them via rotateAll() at render time. 2. Even when the new RMP-cache banners did render, click_url pointed at www.RMP.com//, which logs to adv.banner_clicks. The RMP analytics dashboard reads bb.ad_clicks. Repointed click URLs at advertising.RMP.com/r/ so all clicks land in the single table the dashboard queries. Files: lib/ads.ts (remove broken IIFE exports + repoint click_url), SidebarAdStack, Header, Footer, and 9 pages (reading-list, forum, forum/thread, search, gear, technology, authors, show-coverage x2). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/app/authors/[slug]/page.tsx | 2 +- src/app/forum/page.tsx | 6 +++--- src/app/forum/thread/[id]/page.tsx | 4 ++-- src/app/gear/page.tsx | 6 +++--- src/app/reading-list/page.tsx | 6 +++--- src/app/search/page.tsx | 6 +++--- src/app/show-coverage/[slug]/page.tsx | 6 +++--- src/app/show-coverage/page.tsx | 6 +++--- src/app/technology/page.tsx | 6 +++--- src/components/Footer.tsx | 6 +++--- src/components/Header.tsx | 6 +++--- src/components/SidebarAdStack.tsx | 17 ++++++++++++----- src/lib/ads.ts | 20 ++++++++++---------- 13 files changed, 52 insertions(+), 45 deletions(-) diff --git a/src/app/authors/[slug]/page.tsx b/src/app/authors/[slug]/page.tsx index b163651..79d9978 100644 --- a/src/app/authors/[slug]/page.tsx +++ b/src/app/authors/[slug]/page.tsx @@ -6,7 +6,7 @@ import AppImage from "@/components/ui/AppImage"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; import SidebarAdStack from "@/components/SidebarAdStack"; interface AuthorProfile { diff --git a/src/app/forum/page.tsx b/src/app/forum/page.tsx index a6f8bc6..6b2ea0e 100644 --- a/src/app/forum/page.tsx +++ b/src/app/forum/page.tsx @@ -5,7 +5,7 @@ import Header from '@/components/Header'; import Footer from '@/components/Footer'; import AdImage from '@/components/AdImage'; import SidebarAdStack from '@/components/SidebarAdStack'; -import { ADS_728X90, shuffle } from '@/lib/ads'; +import { pickAds } from '@/lib/ads'; import { createClient } from '@/lib/supabase/client'; interface ForumCategory { @@ -632,9 +632,9 @@ export default function ForumIndexPage() { {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/app/forum/thread/[id]/page.tsx b/src/app/forum/thread/[id]/page.tsx index 32798aa..c668bc1 100644 --- a/src/app/forum/thread/[id]/page.tsx +++ b/src/app/forum/thread/[id]/page.tsx @@ -5,7 +5,7 @@ import { useParams } from 'next/navigation'; import Header from '@/components/Header'; import Footer from '@/components/Footer'; import AdImage from '@/components/AdImage'; -import { ADS_300X250, rotateAll } from '@/lib/ads'; +import { pickAds, rotateAll } from '@/lib/ads'; import { createClient } from '@/lib/supabase/client'; import SidebarAdStack from "@/components/SidebarAdStack"; import LinkifyPlainText from "@/components/LinkifyPlainText"; @@ -13,7 +13,7 @@ import CompanyMentionsHover from "@/components/CompanyMentionsHover"; // Inline ad slot inserted between forum replies every N posts. function InThreadAd({ adIndex }: { adIndex: number }) { - const pool = ADS_300X250; + const pool = rotateAll("300x250"); if (pool.length === 0) return null; const ad = pool[adIndex % pool.length]; return ( diff --git a/src/app/gear/page.tsx b/src/app/gear/page.tsx index 1ac2116..06a4df4 100644 --- a/src/app/gear/page.tsx +++ b/src/app/gear/page.tsx @@ -5,7 +5,7 @@ import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AppImage from "@/components/ui/AppImage"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; import { getLegacyArticlesBySection } from "@/lib/articles/legacy-source"; import SidebarAdStack from "@/components/SidebarAdStack"; @@ -91,9 +91,9 @@ export default async function GearPage() { {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/app/reading-list/page.tsx b/src/app/reading-list/page.tsx index 98d8e6a..2514af8 100644 --- a/src/app/reading-list/page.tsx +++ b/src/app/reading-list/page.tsx @@ -5,7 +5,7 @@ import AppImage from "@/components/ui/AppImage"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; import { createClient } from "@/lib/supabase/client"; import SidebarAdStack from "@/components/SidebarAdStack"; @@ -315,9 +315,9 @@ export default function ReadingListPage() { {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx index 20e3992..1f216bd 100644 --- a/src/app/search/page.tsx +++ b/src/app/search/page.tsx @@ -4,7 +4,7 @@ import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AppImage from "@/components/ui/AppImage"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; import { searchLegacyArticles } from "@/lib/articles/legacy-source"; import SidebarAdStack from "@/components/SidebarAdStack"; @@ -99,9 +99,9 @@ export default async function SearchPage({ searchParams }: SearchPageProps) { {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/app/show-coverage/[slug]/page.tsx b/src/app/show-coverage/[slug]/page.tsx index 18f8e60..e4a109a 100644 --- a/src/app/show-coverage/[slug]/page.tsx +++ b/src/app/show-coverage/[slug]/page.tsx @@ -5,7 +5,7 @@ import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AdImage from "@/components/AdImage"; import SidebarAdStack from "@/components/SidebarAdStack"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; export const dynamic = "force-dynamic"; export const revalidate = 600; @@ -215,9 +215,9 @@ export default async function EventCoveragePage({ {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/app/show-coverage/page.tsx b/src/app/show-coverage/page.tsx index 21f42d3..6daff13 100644 --- a/src/app/show-coverage/page.tsx +++ b/src/app/show-coverage/page.tsx @@ -3,7 +3,7 @@ import { createClient } from "@supabase/supabase-js"; import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; import SidebarAdStack from "@/components/SidebarAdStack"; export const dynamic = "force-dynamic"; @@ -94,9 +94,9 @@ export default async function ShowCoverageIndex() { {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/app/technology/page.tsx b/src/app/technology/page.tsx index 00422a3..3a3d6ac 100644 --- a/src/app/technology/page.tsx +++ b/src/app/technology/page.tsx @@ -5,7 +5,7 @@ import Header from "@/components/Header"; import Footer from "@/components/Footer"; import AppImage from "@/components/ui/AppImage"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; import { getLegacyArticlesBySection } from "@/lib/articles/legacy-source"; import SidebarAdStack from "@/components/SidebarAdStack"; @@ -213,9 +213,9 @@ export default async function TechnologyPage({ searchParams }: PageProps) { {/* In-content 728x90 banner */} - {ADS_728X90.length > 0 && ( + {pickAds("728x90", 1).length > 0 && (
- +
)} diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 8de71f0..415d321 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -8,7 +8,7 @@ import { FacebookIcon } from "@/components/ui/Icons"; import AdImage from "@/components/AdImage"; -import { ADS_728X90, shuffle } from "@/lib/ads"; +import { pickAds } from "@/lib/ads"; // DO NOT OVERRIDE — Footer column structure and link targets const footerColumns = [ @@ -65,9 +65,9 @@ export default function Footer() {