refactor(ads): improve Ezoic ad rendering logic

This commit is contained in:
Fatih Kadir Akın
2026-03-20 00:20:51 +03:00
parent cd1715e703
commit 29064d6ada
2 changed files with 14 additions and 13 deletions
+4 -8
View File
@@ -10,17 +10,13 @@ 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(() => {
// Render the placeholder div first, then tell Ezoic to fill it.
// This ensures the DOM element exists before showAds is called.
setIsRendered(true);
// Use requestAnimationFrame to guarantee the placeholder div
// is in the DOM before Ezoic tries to find it.
// The placeholder div is always in the DOM (including SSR).
// Use requestAnimationFrame to ensure the DOM is fully committed
// before telling Ezoic to fill it.
const rafId = requestAnimationFrame(() => {
runEzoic(() => {
window.ezstandalone?.showAds(id);
@@ -74,7 +70,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>
);
+10 -5
View File
@@ -20,14 +20,19 @@ export function EzoicAds() {
const pathname = usePathname();
const isFirstRender = useRef(true);
// Re-trigger ads on SPA route changes
// Per Ezoic docs: destroyPlaceholders first, then showAds in next frame.
// Skip the first render to avoid racing with individual EzoicPlaceholder
// components that call showAds(id) on mount.
// Re-trigger ads on route changes.
// First render: call global showAds() as a safety net (placeholder divs are in SSR HTML).
// Subsequent renders (SPA navigation): destroyPlaceholders first, then showAds.
useEffect(() => {
if (isFirstRender.current) {
isFirstRender.current = false;
return;
// On initial page load, give placeholders time to mount, then trigger global showAds
const timeoutId = setTimeout(() => {
runEzoic(() => {
window.ezstandalone?.showAds();
});
}, 500);
return () => clearTimeout(timeoutId);
}
runEzoic(() => {
window.ezstandalone?.destroyPlaceholders();