Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,4 @@ dl.facts dd { margin: 0; overflow-wrap: anywhere; }

/* CrawlProof ad unit: no box until ad.js starts filling it, so an unsold or blocked slot leaves no hole. */
.ad-unit { display: flex; flex-direction: column; align-items: center; height: 0; overflow: hidden; }
.ad-unit[data-cp-filled] { height: auto; min-height: 106px; margin: 1.5rem 0; overflow: visible; }
.ad-unit[data-cp-filled][data-format="banner_300x250"] { min-height: 266px; }
.ad-unit[data-cp-filled] { height: auto; min-height: 40px; margin: 10px 0; overflow: visible; align-items: stretch; }
19 changes: 12 additions & 7 deletions src/components/ad-unit.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
"use client";

import { useEffect, useRef } from "react";
import { usePathname } from "next/navigation";

/** CrawlProof ad slot for datamart.help. Manage it at https://crawlproof.com/ads/slots */
const AD_SLOT = "04392e64-733a-48dd-b17b-c4dc9eb3a399";

/** 728px banner plus the .wrap gutters; anything narrower gets the 300x250 rectangle. */
const LEADERBOARD_QUERY = "(min-width: 760px)";

declare global {
interface Window {
crawlproofAds?: { scan: () => void };
}
}

/**
* One CrawlProof unit at the top of the content. The aside is server-rendered without
* data-slot, so ad.js's own DOMContentLoaded pass skips it; the format is picked
* from the real viewport on mount, then we ask ad.js to scan (retrying briefly
* One low-profile CrawlProof text-link unit at the top of the content, on every page
* but the homepage. The aside is server-rendered without data-slot, so ad.js's own
* DOMContentLoaded pass skips it; on mount we set text_link + the slot and ask ad.js to scan (retrying briefly
* until it has loaded, and giving up so an ad blocker leaves no timer running).
* It stays zero-height until ad.js marks it data-cp-filled.
*/
export function AdUnit() {
const pathname = usePathname() ?? "/";
if (pathname === "/") return null;
// Keyed by path so each client-side navigation gets a fresh unit.
return <AdSlot key={pathname} />;
}

function AdSlot() {
const ref = useRef<HTMLElement>(null);

useEffect(() => {
const el = ref.current;
if (!el) return;
el.dataset.format = window.matchMedia(LEADERBOARD_QUERY).matches ? "banner_728x90" : "banner_300x250";
el.dataset.format = "text_link";
el.dataset.slot = AD_SLOT;

let tries = 0;
Expand Down
Loading