feat(web): add CrawlProof ad unit to /blog/*
Some checks failed
CI / build (push) Has been cancelled
test / test (push) Has been cancelled

Reusable AdUnit component (div[data-cp-ad] + ad.js via next/script) placed
in-content on the blog index and post pages, scoped to /blog/* only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-07-08 10:40:00 +00:00
parent 8107140228
commit d76dd498f2
3 changed files with 29 additions and 0 deletions

View file

@ -4,6 +4,7 @@ import type { ReactNode } from "react";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { publicClient } from "@/lib/supabase"; import { publicClient } from "@/lib/supabase";
import { SiteShell } from "@/components/site-shell"; import { SiteShell } from "@/components/site-shell";
import { AdUnit } from "@/components/ad-unit";
import { sanitizeRenderedHtml } from "@/lib/html"; import { sanitizeRenderedHtml } from "@/lib/html";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -118,6 +119,9 @@ export default async function BlogPostPage({
style={{ lineHeight: 1.7 }} style={{ lineHeight: 1.7 }}
dangerouslySetInnerHTML={{ __html: html }} dangerouslySetInnerHTML={{ __html: html }}
/> />
<div style={{ display: "flex", justifyContent: "center", marginTop: "2.5rem" }}>
<AdUnit slot="709f4f1d-667a-4888-9040-90f5f65120f2" format="banner_300x250" />
</div>
</article> </article>
</SiteShell> </SiteShell>
); );

View file

@ -3,6 +3,7 @@ import type { ReactNode } from "react";
import type { Metadata } from "next"; import type { Metadata } from "next";
import { publicClient } from "@/lib/supabase"; import { publicClient } from "@/lib/supabase";
import { SiteShell } from "@/components/site-shell"; import { SiteShell } from "@/components/site-shell";
import { AdUnit } from "@/components/ad-unit";
export const dynamic = "force-dynamic"; export const dynamic = "force-dynamic";
@ -123,6 +124,10 @@ export default async function BlogIndex(): Promise<ReactNode> {
})} })}
</ul> </ul>
)} )}
<div style={{ display: "flex", justifyContent: "center", marginTop: "2rem" }}>
<AdUnit slot="709f4f1d-667a-4888-9040-90f5f65120f2" format="banner_300x250" />
</div>
</div> </div>
</SiteShell> </SiteShell>
); );

View file

@ -0,0 +1,20 @@
import type { ReactNode } from "react";
import Script from "next/script";
// CrawlProof ad unit, scoped to the pages that render it (currently /blog/*).
// The loader is deduped by src, so mounting <AdUnit /> on multiple routes only
// injects one https://crawlproof.com/ad.js.
export function AdUnit({
slot,
format = "banner_300x250",
}: {
slot: string;
format?: string;
}): ReactNode {
return (
<>
<div data-cp-ad data-slot={slot} data-format={format} />
<Script src="https://crawlproof.com/ad.js" strategy="afterInteractive" />
</>
);
}