Skip to content

Instantly share code, notes, and snippets.

@ArrayIterator
Last active February 24, 2025 03:26
Show Gist options
  • Save ArrayIterator/fd0e9b7a112fddbd49bd4e07735c785b to your computer and use it in GitHub Desktop.
Save ArrayIterator/fd0e9b7a112fddbd49bd4e07735c785b to your computer and use it in GitHub Desktop.
Google Adsense Implementation for non GPT (Google Publisher Tag)
import React, {createRef, useEffect, useState} from 'react';
import {CSSProperties, ReactNode} from 'react';
import AdsenseJS from './AdsenseJS';
declare var window: Window&{
adsbygoogle: any[],
};
const IS_SSR = typeof window !== 'object' || !window || typeof window.document !== 'object';
export function Adsense(props: {
slot: string,
client: string,
className?: string,
style?: CSSProperties,
layout?: string,
layoutKey?: string,
format?: "auto" | "fluid",
responsive?: "true" | "false",
}) : ReactNode {
const adSlotRef = createRef<HTMLModElement>();
const [mounted, setMounted] = useState(IS_SSR);
const {className, style, client, slot, layout, layoutKey, format, responsive} = {...props};
useEffect(() => {
setMounted(true); // for strict mode
return () => setMounted(false);
}, []);
useEffect(() => {
if (!mounted) {
return;
}
try {
if (adSlotRef.current
&& undefined === (adSlotRef.current as HTMLModElement & {
pushed?: boolean
}).pushed) {
(window.adsbygoogle = window.adsbygoogle || []);
window.adsbygoogle.push({});
Object.defineProperty(adSlotRef.current, 'pushed', {
value: true,
writable: false,
})
}
} catch {
// do nothing
}
}, [adSlotRef.current, mounted]);
if (!mounted) {
return null;
}
return (
<>
<ins
data-ad-slot={slot}
data-ad-client={client}
style={style || {}}
className={className?.includes('adsbygoogle') ? className : `adsbygoogle ${className||''}`}
data-full-width-responsive={responsive === 'true' ? 'true' : 'false'}
data-ad-format={format || 'auto'}
data-ad-layout-key={layoutKey || ''}
data-ad-layout={layout || ''}
ref={adSlotRef}
/>
{/*include adsense-js once*/}
<AdsenseJS/>
</>
)
}
// usage: <Adsense slot="1234567890" client="ca-pub-1234567890" className="adsbygoogle" style={{display: 'block'}} layout="in-article" format="fluid" responsive="true"/>
import {forwardRef, useEffect, useImperativeHandle, useRef, useState} from 'react';
import React from 'react';
const IS_SSR = typeof window !== 'object' || !window || typeof window.document !== 'object';
const GOOGLE_JS_URI = '//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js';
const GOOGLE_JS = `https:${GOOGLE_JS_URI}`;
const ID = 'adsense-js-script';
const loaded = IS_SSR || (
(document.querySelector(`script#${ID}`) as HTMLScriptElement)
?.getAttribute('src')
?.split('#')[0].split('?')[0]
.endsWith(GOOGLE_JS)
|| false
);
const AdsenseJS = forwardRef((props, ref) => {
const [mounted, setMounted] = useState(IS_SSR);
const [scriptLoaded, setScriptLoaded] = useState(loaded);
const scriptRef = useRef<null|HTMLScriptElement>(null);
useEffect(() => {
setMounted(true);
return () => setMounted(false);
}, []);
useEffect(() => {
if (mounted && !scriptLoaded) {
if (!scriptRef.current) {
const script = document.createElement('script');
script.id = 'adsense-js-script';
script.async = true;
script.src = GOOGLE_JS;
script.crossOrigin = 'anonymous';
script.onload = () => {
setScriptLoaded(true);
};
scriptRef.current = script;
document.head.appendChild(script);
} else if (scriptRef.current.parentNode !== document.head) {
document.head.appendChild(scriptRef.current);
setScriptLoaded(true);
} else {
setScriptLoaded(true);
}
}
}, [mounted, scriptLoaded]);
useImperativeHandle(ref, () => ({
isLoaded: scriptLoaded,
reload: () => {},
}));
if (IS_SSR) {
return <script id={ID} src={GOOGLE_JS} async crossOrigin="anonymous"/>;
}
return null;
});
export default AdsenseJS;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment