google-adsense
Version:
Add Google AdSense to your React project instantly. This simple component handles both auto and manual ad setup.
95 lines (94 loc) • 4.72 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { useEffect, useRef, useState } from "react";
/**
* A React component for displaying Google AdSense ads.
* Supports both manual ad placements and Auto Ads.
*/
const AdSense = ({ client, slot, format = "auto", style = { display: "block", minHeight: "90px" }, // Ensuring minimum height to prevent zero-height errors
className, containerClass, layout, layoutKey, layoutDensity, fullWidthResponsive = false, // Default to false
width = "100%", // Ensure a valid width
height = "auto", // Ensure a valid height
}) => {
const adRef = useRef(null);
const [showAd, setShowAd] = useState(true);
const [scriptLoaded, setScriptLoaded] = useState(false);
useEffect(() => {
if (!slot || !adRef.current)
return;
const adElement = adRef.current.querySelector("ins");
if (!adElement)
return;
// MutationObserver to check if the ad failed to load
const observer = new MutationObserver(() => {
const adStatus = adElement.getAttribute("data-ad-status");
if (adStatus === "unfilled") {
console.warn("AdSense returned an unfilled ad. Rechecking in 3 seconds; if it remains unloaded, it will be removed...");
setTimeout(() => {
if (adElement.getAttribute("data-ad-status") === "unfilled") {
console.warn("AdSense ad unfilled, removing.");
setShowAd(false);
observer.disconnect();
}
}, 3000); // Wait 3 seconds before removing
}
});
observer.observe(adElement, {
attributes: true, // Observe changes to attributes
attributeFilter: ["data-ad-status"],
});
// Push ad immediately if adsbygoogle exists
if (window.adsbygoogle) {
try {
window.adsbygoogle.push({});
}
catch (e) {
console.error("AdSense push error: ", e);
setShowAd(false);
}
}
return () => observer.disconnect();
}, [client, slot]);
useEffect(() => {
const scriptUrl = `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${client}`;
// Check if the AdSense script is already loaded to prevent duplicate loading.
if (!document.querySelector(`script[src="${scriptUrl}"]`)) {
const script = document.createElement("script");
script.src = scriptUrl;
script.async = true;
script.crossOrigin = "anonymous"; // Recommended for security.
document.head.appendChild(script); // Place in <head> for better performance.
/**
* Callback function to execute after the AdSense script has loaded.
*/
script.onload = () => {
console.log("AdSense script loaded.");
setScriptLoaded(true); // Set script loaded state
// Push an empty object to adsbygoogle to trigger ad display for manual placements
// *after* the script loads, ensuring adsbygoogle is defined.
if (window.adsbygoogle) {
window.adsbygoogle.push({});
}
};
/**
* Callback function to execute if the AdSense script fails to load.
*/
script.onerror = () => {
console.error("Failed to load Google AdSense script.");
setScriptLoaded(false); // Set script loaded state to false
};
}
else {
// Ensures that scriptLoaded reflects the actual state of adsbygoogle, preventing potential issues
// where scriptLoaded is set to true even if adsbygoogle is undefined.
setScriptLoaded(!!window.adsbygoogle);
}
}, []);
// If no 'slot' is provided, it's assumed to be Auto Ads.
// Auto Ads handles the script inclusion and ad placement automatically,
// so we return null to avoid rendering a redundant script tag.
if (!showAd || !slot)
return null;
// Manual ad placement: render the <ins> tag.
return (_jsx("div", { ref: adRef, style: { width, height }, className: containerClass, children: _jsx("ins", { className: `adsbygoogle ${className || ""}`, "data-ad-client": client, "data-ad-slot": slot, "data-ad-format": format, "data-ad-layout": layout, "data-ad-layout-key": layoutKey, "data-ad-layout-density": layoutDensity, "data-full-width-responsive": fullWidthResponsive ? "true" : "false", style: { ...style, width, height } }) }));
};
export default AdSense;