UNPKG

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
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;