代码之家  ›  专栏  ›  技术社区  ›  PayteR

Google DFP-从内部调整SafeFrame自定义创造性外部Iframe容器的大小(扩展广告)

  •  5
  • PayteR  · 技术社区  · 7 年前

    2 回复  |  直到 7 年前
        1
  •  8
  •   PayteR    7 年前

    有两种可能的解决方案:

    1) 使用 SafeFrame API

    赞成的意见:

    • 你可以在任何网站上使用它,不需要在网站上自定义代码

    • 它仅限于填充网站的可见区域
    • 需要等待,直到用户看到广告单元

    2) 使用编写自己的API window.postMessage()

    欺骗:

    • 您需要向网站添加自定义代码

    赞成的意见:

    1) 使用

    GPT Safeframe preview tool .

    首先,您需要在中更新DFP初始化脚本 <head> 您网站的

    var pageConfig = {
        allowOverlayExpansion: true,
        allowPushExpansion: true,
        sandbox: true
    };
    googletag.pubads().setSafeFrameConfig(pageConfig);
    

    这将允许在您的网站上扩展安全框架广告。更多信息请访问 Control SafeFrame Container behavior through GPT

    现在你可以创建自定义创意,并将其作为网站的安全框架。这是我的一个例子。这个例子可以“等待”直到它可见,然后将扩展到的高度 <div id="container"> 在安全框架内:

    <div id="container">
        some lines to make container height<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
        line<br>
    </div>
    
    <script>
        // global expanded indicator variable, because API don't have any
        var expanded = false;
        function expand() {
            var self= $sf.ext.geom().self;
            var config = {
                push: true, // we want to push expanded content
                b: 0
            };
    
            var el = document.getElementById('container');
            var containerHeight = el.offsetHeight;
    
            // get height from bottom, that need to be expanded
            var expandBottom = containerHeight - self.h;
    
            // if container is whole inside a SafeFrame, it will not expand
            if(expandBottom < 0) return;
    
            config.b = expandBottom;
            $sf.ext.expand(config);
        }
    
        function expandDelayed(forceExpand) {
            // expand will run just once, or you can force it to run again
            // but collapse first is needed
            if(expanded && forceExpand || !expanded) {
                $sf.ext.collapse();
                expanded = false;
                // there must be some timeout, because .collapse(); method is deplayed somehow
                setTimeout(expand, 0);
            }
        }
    
        $sf.ext.register(160, 150, function(status, data) {
            // this code will do whole magic of "waiting" for right moment
            if (status === 'geom-update') {
                expandDelayed();
            }
    
            // change global expanded status
            if (status === 'expanded') {
                expanded = true;
            }
        });
    
        // init
        expandDelayed();
    </script>
    

    javascript方法

    首先,您需要将此代码放入DFP初始化脚本中 < 您的网站。此代码将添加广告槽的ID作为 #hash-tag <iframe>

    googletag.pubads().addEventListener('slotRenderEnded', function (event) {
        var containerId = event.slot.getSlotElementId();
        var containerEl = document.getElementById(containerId);
    
        if (containerEl === null) return;
    
        var iframeEl = containerEl.querySelectorAll('iframe')[0];
    
        // it's delayed by 10 milliseconds, because iframe is not yet fully rendered
        // and limited to max to 10 seconds to wait 
        var timeoutFunction = function () {
            var src = "#" + containerId;
            // `src` attribute is null, when iframe is FriendlyIframe, and
            // when it's present, then it's SafeFrame
            if (iframeEl.getAttribute('src') !== null) {
                src = iframeEl.getAttribute('src').replace(/#.*/, "") + src;
            } else {
                var name = iframeEl.getAttribute('name') + "#" + containerId;
                iframeEl.setAttribute('name', name);
            }
            iframeEl.setAttribute('src', src);
        };
        setTimeout(timeoutFunction, 10);
    });
    

    第二,你需要把这些代码添加到你的网站上,最好分开。js文件。

    function onMessageReceivedGetStyle(e) {
    
        // this will filter just setStyle commands from correct origin
        if (
            !(e.origin === 'http://tpc.googlesyndication.com' || e.origin === 'https://tpc.googlesyndication.com') ||
            typeof e.data !== 'object' ||
            typeof e.data.id !== 'string' ||
            e.data.cmd !== 'setStyle' ||
            typeof e.data.params !== 'object'
        ) {
            return;
        }
    
        // remove # character from id, we don't use jquery
        var elementId = e.data.id.replace(/#/, "");
    
        var wrapperEl = document.getElementById(elementId);
        if (wrapperEl === null) {
            return;
        }
    
        var elements = [wrapperEl];
        // you can target child elements too with query parameter
        if (typeof e.data.query === 'string' && e.data.query) {
            elements = wrapperEl.querySelectorAll(e.data.query);
        }
    
        elements.forEach(function (element) {
            Object.keys(e.data.params).forEach(function (param) {
                element.style[param] = e.data.params[param];
            });
        });
    
    }
    
    if (window.addEventListener) {
        addEventListener('message', onMessageReceivedGetStyle, false);
    }
    else {
        if (window.attachEvent) {
            attachEvent('onmessage', onMessageReceivedGetStyle);
        }
        else {
            window.onmessage = onMessageReceivedGetStyle;
        }
    }
    

    iframe with creative:

    <div id="container">
        <a href="#" target="_blank">
            <img src="%%FILE:JPG1%%">
        </a>
        <a href="#" target="_blank">
            <img src="%%FILE:JPG2%%">
        </a>
    </div>
    
    <style>
        a {
            display: block;
            margin-bottom: .5em;
        }
        img {
            display: block;
            max-width: 100%;
        }
        *:last-child {
            margin-bottom: 0;
        }
    </style>
    
    <script>
        var container = document.getElementById('container');
    
        function resizeOutsideSafeFrame() {
            if (!window.top.postMessage) {
                return false;
            }
    
            // get ID of your Ad unit <div> with this creative 
            var divGptAdId = '%%PATTERN:url%%';
    
            if (divGptAdId.indexOf('#') !== -1) {
                divGptAdId = divGptAdId.split('#')[1];
            } else {
                divGptAdId = window.location.hash;
            }
    
            if(!divGptAdId) {            
                if (window.name.indexOf('#') !== -1) {               
                    divGptAdId = window.name.split('#')[1];
                }
            }
    
            if(!divGptAdId) {
                return;
            }
    
            // set with to fullwidth, and height to height of container inside creative
            var width = '100%';
            var height = container.offsetHeight + 'px';
    
            // send our request to website
            window.top.postMessage({
                cmd: 'setStyle',
                id: divGptAdId,
                query: 'div, iframe', // we want to target child div and iframe and don't change container styles
                params: {
                    display: 'block',
                    height: height,
                    width: width
                }
            }, '*');
        }
    
        document.onreadystatechange = function () {
            // resize iframe when all is loaded
            if (document.readyState == "complete") {
                resizeOutsideSafeFrame();
            }
        };
    
        // first resize must occur little bit later 
        setTimeout(resizeOutsideSafeFrame, 100);
    </script>
    

    并从iframe内部调用此命令。


    编辑1: 刚刚注意到 var divGptAdId = '%%PATTERN:url%%;

    if(!divGptAdId) {
        return;
    }
    

    if(!divGptAdId) { 
        divGptAdId = 'div-gpt-ad-container-div-id-1';
    }
    
        2
  •  1
  •   Richard    7 年前

    下面是我根据PayteR的示例创建的一些示例代码:

    /* Main object for namespacing */
    var Ad = function(obj) {};
    
    /* 
      Register your ad with the dimensions of the current ad.
      - This is basically an event handler for the the ad frame.
      - 728 initial ad width
      - 90 initial ad height
    */
    Ad.prototype.registerExpand = function() {
      $sf.ext.register(728, 90, function(status, data){});
    };
    
    /* Expand function to be called on click or load */
    Ad.prototype.expandAd = function() {
    
      /* Get the current geometry of your ad */
      var self = $sf.ext.geom().self;
    
      /* 
        Set the new geometry
        - Increase height 315 pixels
        - Expand downward by setting the bottom to the new height minus the current height
      */
      $sf.ext.expand({
        h: 315,
        b: 315 - self.h
      });
    };
    
    
    /* Intialize, register, and expand */
    var ad = new Ad();
    ad.registerExpand();
    ad.expandAd();