refactor(components): refactor Ezoic ad and placeholder components
Entire-Checkpoint: afbec17cde9f
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { EzoicPlaceholder } from "./ezoic-placeholder";
|
||||
|
||||
interface EzoicAdProps {
|
||||
@@ -8,20 +7,10 @@ interface EzoicAdProps {
|
||||
}
|
||||
|
||||
/**
|
||||
* Client-only wrapper that defers EzoicPlaceholder mounting until after
|
||||
* hydration. This matches the feed widget pattern where InfinitePromptList
|
||||
* gates widget rendering behind an isMounted state, ensuring EzoicPlaceholder
|
||||
* mounts in a separate render pass — after EzoicAds route handler has
|
||||
* completed its initial destroyPlaceholders/showAds cycle.
|
||||
* Client-only wrapper for EzoicPlaceholder.
|
||||
* The placeholder div is always rendered so it's in the DOM when
|
||||
* Ezoic's showAds() runs — no deferred mounting needed.
|
||||
*/
|
||||
export function EzoicAd({ id }: EzoicAdProps) {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
if (!mounted) return null;
|
||||
|
||||
return <EzoicPlaceholder id={id} />;
|
||||
}
|
||||
|
||||
@@ -10,15 +10,16 @@ interface EzoicPlaceholderProps {
|
||||
|
||||
export function EzoicPlaceholder({ id }: EzoicPlaceholderProps) {
|
||||
const t = useTranslations("common");
|
||||
const [isRendered, setIsRendered] = useState(false);
|
||||
const [hasAdContent, setHasAdContent] = useState(true);
|
||||
const placeholderRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Per Ezoic Next.js docs: render the placeholder div first (via state),
|
||||
// then call showAds(id). The global EzoicRouteHandler's showAds() call
|
||||
// acts as a safety net to catch all placeholders.
|
||||
setIsRendered(true);
|
||||
// The placeholder div is always rendered (no conditional gating),
|
||||
// so it's in the DOM when this effect runs. Call showAds(id) to
|
||||
// tell Ezoic to fill it. The global EzoicAds route handler's
|
||||
// showAds() call acts as an additional safety net.
|
||||
const el = placeholderRef.current;
|
||||
|
||||
runEzoic(() => {
|
||||
window.ezstandalone?.showAds(id);
|
||||
});
|
||||
@@ -26,7 +27,6 @@ export function EzoicPlaceholder({ id }: EzoicPlaceholderProps) {
|
||||
// Observe the placeholder for ad content injection by Ezoic.
|
||||
// If nothing is injected after a timeout, hide the container
|
||||
// to avoid showing an empty white card.
|
||||
const el = document.getElementById(`ezoic-pub-ad-placeholder-${id}`);
|
||||
let observer: MutationObserver | undefined;
|
||||
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
||||
|
||||
@@ -69,7 +69,7 @@ export function EzoicPlaceholder({ id }: EzoicPlaceholderProps) {
|
||||
</span>
|
||||
</div>
|
||||
<div className="ezoic-ad-content overflow-hidden flex items-center justify-center">
|
||||
{isRendered && <div id={`ezoic-pub-ad-placeholder-${id}`} ref={placeholderRef} />}
|
||||
<div id={`ezoic-pub-ad-placeholder-${id}`} ref={placeholderRef} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -25,10 +25,15 @@ export function EzoicAds() {
|
||||
useEffect(() => {
|
||||
runEzoic(() => {
|
||||
window.ezstandalone?.destroyPlaceholders();
|
||||
requestAnimationFrame(() => {
|
||||
});
|
||||
// Delay the global showAds() to give React time to render all
|
||||
// placeholder divs into the DOM after route change.
|
||||
const timer = setTimeout(() => {
|
||||
runEzoic(() => {
|
||||
window.ezstandalone?.showAds();
|
||||
});
|
||||
});
|
||||
}, 100);
|
||||
return () => clearTimeout(timer);
|
||||
}, [pathname]);
|
||||
|
||||
return (
|
||||
@@ -47,18 +52,20 @@ export function EzoicAds() {
|
||||
data-cfasync="false"
|
||||
/>
|
||||
|
||||
{/* Ezoic init — must run before sa.min.js so the cmd queue exists */}
|
||||
<Script id="ezoic-init" strategy="beforeInteractive">
|
||||
{`
|
||||
window.ezstandalone = window.ezstandalone || {};
|
||||
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
||||
`}
|
||||
</Script>
|
||||
|
||||
{/* Ezoic Header Script */}
|
||||
<Script
|
||||
id="ezoic-sa"
|
||||
src="//www.ezojs.com/ezoic/sa.min.js"
|
||||
strategy="afterInteractive"
|
||||
/>
|
||||
<Script id="ezoic-init" strategy="afterInteractive">
|
||||
{`
|
||||
window.ezstandalone = window.ezstandalone || {};
|
||||
window.ezstandalone.cmd = window.ezstandalone.cmd || [];
|
||||
`}
|
||||
</Script>
|
||||
|
||||
{/* Ezoic Analytics */}
|
||||
<Script
|
||||
|
||||
Reference in New Issue
Block a user