Languages
[Edit]
EN

React - Google Ads / GPT with fluid size on web page

10 points
Created by:
chelsea
326

In this article we would like to show trick how in React use Google Ads / GPT in fluid size mode.

Fluid size for Google Ad / GPT achieved with transformation.
Fluid size for Google Ad / GPT achieved with transformation.

By default fluid size mode is not supported on web pages but there is some trick how to scale Ad with transform scale style. The main idea of the below solution is to display Google Ad in supported size defined in Google Ads Panel, keeping aspect ratio and scale Ad to the desired size - container size - size for below container component is set with style property. That approach is useful on mobile devices where we want to scale Ads to fill some area on out web page.

Notes:

  • if example doesn't work copy it to your web site and run it under your domain (it can do not work on localhost or in local file run in web browser),
  • go to this article to read about not scalled Google Ads / GPT in React,
  • go to this article to see component that scales content with transform scale style what was used in this aticle - ContentStretcher component.

Hint: in some cases it can be necessary to run slot.display(); when Ad containg DOM element is ready - you can try to use setTimeout with delay >=100ms as some trick.

Practical example: 

// ONLINE-RUNNER:browser;

<!doctype html>
<html>
<head>
  
  <!-- Required only to run React code in this example -->
  <script src="https://unpkg.com/react/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  
  <!-- Google Ads / GPT import - attach it to yours project -->
  <script src="https://www.googletagservices.com/tag/js/gpt.js"></script>

</head>
<body>
  <div id="root"></div>
  <!-- copy below script body to React project -->
  <script type="text/babel">

	// Note: Uncomment import lines during working with JSX Compiler.
    // import React from 'react';
    // import ReactDOM from 'react-dom';
    
    const googletag = window.googletag || (window.googletag = { cmd: [] });
    
    const createScope = (action) => action && action();
    
    const GPTAdsManager = createScope(() => {
        let initialized = false;
        const initializeAds = (initialLoading = false, singleRequest = true) => {
            if (initialized) {
               	return;
            }
            initialized = true;
            googletag.cmd.push(() => {
                const pubads = googletag.pubads();
                if (!initialLoading) {
                  	pubads.disableInitialLoad();
                }
                if (singleRequest) {
                  	pubads.enableSingleRequest();
                }
                googletag.enableServices();
          	});
        };
        const createSlot = (adPath, adWidth, adHeight, elementId) => {
            initializeAds(); // only if not initialized yet
            let slot = null;
            googletag.cmd.push(() => {
                const size = adWidth & adHeight ? [adWidth, adHeight] : ['fluid'];
                const tmp = googletag.defineSlot(adPath, size, elementId);
                if (tmp) {
                    slot = tmp;
                    tmp.addService(googletag.pubads());
                }
            });
            const display = () => {
                if (slot) {
                    googletag.cmd.push(() => {
                        const pubads = googletag.pubads();
                        pubads.refresh([slot]);
                    });
                }
            };
            const refresh = () => {
                if (slot) {
                    googletag.cmd.push(() => {
                        const pubads = googletag.pubads();
                        pubads.refresh([slot]);
                    });
                }
            };
           	const destroy = () => {
                if (slot) {
                    const tmp = slot;
                    googletag.cmd.push(() => {
                        const pubads = googletag.pubads();
                        googletag.destroySlots([tmp]);
                    });
                    slot = null;
                }
            };
            return { display, refresh, destroy };
        }
        return { initializeAds, createSlot };
    });

    const AutoSizer = React.memo(({ interval, children, ...other }) => {
        const reference = React.useRef();
        const [size, setSize] = React.useState();
        React.useEffect(() => {
            let storedWidth = size?.width;
            let storedHeight = size?.height;
            const id = setInterval(() => {
                const element = reference.current;
                if (element) {
                    const width = element.offsetWidth;
                    const height = element.offsetHeight;
                    if (width != storedWidth || height != storedHeight) {
                        storedWidth = width;
                        storedHeight = height;
                        setSize({ width, height });
                    }
                }
            }, interval ?? 100);
            return () => {
                clearInterval(id);
            }; 
        }, [interval]);
        return (
          <div ref={reference} {...other}>
            {size && children && children(size.width, size.height)}
          </div>
        );
    });

    const ContentStretcher = ({sizerInterval, contentWidth, contentHeight, children, ...other}) => (
      <AutoSizer 
        {...other}
        style={{
          ...other.style,
          position: 'relative',
          display: 'flex'
        }}
        interval={sizerInterval}
      >
        {(containerWidth, containerHeight) => {
            const contentScale = 
                  containerHeight * contentWidth < containerWidth * contentHeight
                ? containerHeight / contentHeight 
                : containerWidth / contentWidth;
            return (
              <div 
                style={{
                  position: 'absolute',
                  left: '50%',
                  top: '50%',
                  transform: `translate(-50%, -50%) scale(${contentScale})`,
                  transformOrigin: '50% 50%',
                }}
              >
                {children}
              </div>
            );
        }}
      </AutoSizer>
    );

    let adCounter = 0;

    const Ad = ({ path, width, height }) => {
    	const id = React.useMemo(() => `div-gpt-ad-${++adCounter}`, []);
        React.useEffect(() => {
            const slot = GPTAdsManager.createSlot(path, width, height, id);
            slot.display();
            // slot.refresh(); // forces Ad reloading
            return () => {
               	slot.destroy();
            };
        }, [path, width, height]);
		return (
          <div id={id} />
        );
    };
    
    const FluidAd = ({ adPath, adWidth, adHeight, ...other }) => (
      <ContentStretcher 
        {...other}
        contentWidth={adWidth}
        contentHeight={adHeight}
      >
        <Ad path={adPath} width={adWidth} height={adHeight} />
      </ContentStretcher>
    );

	// Usage example:

	// somewhere in the code...
	GPTAdsManager.initializeAds(false, true);        

	// uncomment below 3 lines to open GPT Ads console
    // window.googletag.cmd.push(() => {
    //     window.googletag.openConsole();
    // });

    const App = () => (
	  <div className="App">
	    <FluidAd
          style={{width: '500px', height: '420px'}}
          adPath="/6355419/Travel/Europe/body"
          adWidth={300}
          adHeight={250}
        />
	  </div>
	);

	const root = document.querySelector('#root');
	ReactDOM.render(<App />, root );

  </script>
</body>
</html>

The article describes the situation in Feb 2021.

Note: be sure that Ad size (adWidth and adHeight) has always the same size to prevent unnecessary Ad recreation - or change it consciously according to new slot configurations.

ReactJS

React - Google Ads / GPT with fluid size on web page
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

â€ïžđŸ’» 🙂

Join