本文介绍了Google DFP - 从内部调整 SafeFrame 自定义创意外部 iframe 容器的大小(展开广告)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找可以从 Google DFP 中的自定义广告素材内部扩展 SafeFrame 自定义广告的解决方案,这有可能吗?

解决方案

有两种可能的解决方案:

1) 使用 SafeFrame API

优点:

  • 您可以开箱即用"使用它
  • 您可以在任何网站上使用它,不需要网站上的自定义代码
  • 使用起来很安全

缺点:

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

2) 使用 window.postMessage() javascript 方法

编写您自己的 API

缺点:

  • 您需要向您的网站添加自定义代码
  • 如果您使用某些第 3 方广告素材,这可能是一种威胁

优点:

  • 您几乎可以通过您的广告素材在您的网站上做任何事情

1) 使用 SafeFrame API

这个API真的很容易使用,你可以在GPT Safeframe 预览工具.

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

var pageConfig = {allowOverlayExpansion: 真,allowPushExpansion: 真,沙盒:真实};googletag.pubads().setSafeFrameConfig(pageConfig);

这将允许在您的网站上扩展 SafeFrame 广告.更多关于这个在通过 GPT 控制 SafeFrame 容器行为.

现在您可以创建自定义广告素材并将其作为 SafeFrame 投放到您的网站上.这是我的一个例子.这个例子可以等待"util它是可见的,然后将扩展到<div id="container">的高度,它在SafeFrame里面:

一些用于制作容器高度的线条<br>线
线
线
线
线
线
线
线
线
线
线
线
线
线
线
线
线

<脚本>//全局扩展指标变量,因为 API 没有任何var 扩展 = 假;函数展开(){var self= $sf.ext.geom().self;变量配置 = {push: true,//我们要推送扩展的内容乙:0};var el = document.getElementById('容器');var containerHeight = el.offsetHeight;//从底部获取需要扩展的高度var expandBottom = containerHeight - self.h;//如果容器在 SafeFrame 内是完整的,则不会展开if(expandBottom

2.使用 window.postMessage() javascript 方法

编写您自己的 API

首先,您需要将此代码放入您网站 中的 DFP 初始化脚本中.此代码会将作为 #hash-tag 的广告位 ID 添加到 的 src,以便您可以从广告素材内部获取它.

googletag.pubads().addEventListener('slotRenderEnded', function (event) {var containerId = event.slot.getSlotElementId();var containerEl = document.getElementById(containerId);if (containerEl === null) 返回;var iframeEl = containerEl.querySelectorAll('iframe')[0];//它延迟了 10 毫秒,因为 iframe 还没有完全渲染//并限制为最多 10 秒等待var timeoutFunction = function () {var src = "#" + containerId;//`src` 属性为空,当 iframe 为 FriendlyIframe 时,并且//当它存在时,它就是 SafeFrameif (iframeEl.getAttribute('src') !== null) {src = iframeEl.getAttribute('src').replace(/#.*/, "") + src;} 别的 {var name = iframeEl.getAttribute('name') + "#" + containerId;iframeEl.setAttribute('name', name);}iframeEl.setAttribute('src', src);};setTimeout(timeoutFunction, 10);});

其次,您需要将此代码添加到您的网站,最好是单独的 .js 文件.

function onMessageReceivedGetStyle(e) {//这将过滤来自正确来源的 setStyle 命令如果 (!(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'){返回;}//从 id 中删除 # 个字符,我们不使用 jqueryvar elementId = e.data.id.replace(/#/, "");var wrapperEl = document.getElementById(elementId);如果(wrapperEl === null){返回;}var 元素 = [wrapperEl];//您也可以使用查询参数来定位子元素if (typeof e.data.query === 'string' && e.data.query) {元素 = wrapperEl.querySelectorAll(e.data.query);}element.forEach(函数(元素){Object.keys(e.data.params).forEach(function (param) {element.style[param] = e.data.params[param];});});}如果(window.addEventListener){addEventListener('message', onMessageReceivedGetStyle, false);}别的 {如果(window.attachEvent){attachEvent('onmessage', onMessageReceivedGetStyle);}别的 {window.onmessage = onMessageReceivedGetStyle;}}

第三件事是您在 DFP 中自定义类型的广告素材中的自定义代码.这是示例,类似于第一个例子,但这里这个脚本可以等到所有内容和图像都加载完毕,然后将扩展/缩小您的带有创意的 iframe:

<a href="#" target="_blank"><img src="%%FILE:JPG1%%"></a><a href="#" target="_blank"><img src="%%FILE:JPG2%%"></a>

<风格>一个 {显示:块;底边距:0.5em;}图片{显示:块;最大宽度:100%;}*:最后一个孩子 {底边距:0;}</风格><脚本>var container = document.getElementById('container');函数 resizeOutsideSafeFrame() {如果(!window.top.postMessage){返回假;}//获取您的广告单元的 ID

有了这个创意var divGptAdId = '%%PATTERN:url%%';如果 (divGptAdId.indexOf('#') !== -1) {divGptAdId = divGptAdId.split('#')[1];} 别的 {divGptAdId = window.location.hash;}如果(!divGptAdId){if (window.name.indexOf('#') !== -1) {divGptAdId = window.name.split('#')[1];}}如果(!divGptAdId){返回;}//设置为全宽,高度为广告素材内容器的高度var 宽度 = '100%';var height = container.offsetHeight + 'px';//将我们的请求发送到网站window.top.postMessage({cmd: 'setStyle',id:divGptAdId,query: 'div, iframe',//我们要定位子 div 和 iframe 并且不改变容器样式参数:{显示:'块',高度:高度,宽度:宽度}}, '*');}document.onreadystatechange = 函数 () {//加载所有内容后调整 iframe 的大小如果(document.readyState ==完成"){resizeOutsideSafeFrame();}};//第一次调整大小必须稍后发生setTimeout(resizeOutsideSafeFrame, 100);

仅此而已.当您想从 iframe 内部更改网站上的任何内容时,您可以在您的网站并从 iframe 内部调用此命令.

现在才注意到,var divGptAdId = '%%PATTERN:url%%; 不会以#hash 方式在页面上返回正确的 div id,所以现在需要给他一个正确的容器 divID 更改:

if(!divGptAdId) {返回;}

if(!divGptAdId) {divGptAdId = 'div-gpt-ad-container-div-id-1';}

i'm searching for solution, that can expand SafeFrame custom ad from inside of custom creative in Google DFP, is that possible somehow?

解决方案

There are 2 possible solutions:

1) using SafeFrame API

pros:

  • u can use it "out of the box"
  • you can use it on any website, no custom code on website is needed
  • it's safe to use

cons:

  • it's limited to fill just visible area of website
  • need to wait, until ad unit is visible to the user

2) code your own API with window.postMessage() javascript method

cons:

  • you need to add custom code to your website
  • it's a possible threat, if you use some 3th party creatives

pros:

  • you can do almost anything with your website from your creative

1) using SafeFrame API

This API is realatively easy to use, you can see some examples inGPT Safeframe preview tool.

First you need to update your DFP initialization script in <head> of your website

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

This will allow to expand SafeFrame ads on your website. More about this in Control SafeFrame Container behavior through GPT.

Now you can create custom creative and serve it as SafeFrame on your website. Here is my one example. This Example can "wait" util it's visible, and then will expand to height of <div id="container"> that is inside of SafeFrame:

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

2. code your own API with window.postMessage() javascript method

First, you need to put this code, to your DFP initialization script in <head> of your website. This code will add an ID of Ad slot as #hash-tag to <iframe>'s src so you can get it from inside of your creative.

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

Second, you need to add this code to your website, better as separated .js file.

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

And third thing is your custom code in custom type of creative in DFP. Here is example, that is similar to that infirst example, but here this script can wait until all content and image is loaded and then will expand/shrink youriframe 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>

That's all. When you want to change anything on your website from inside of iframe, you can code your own cmd on yourwebsite and call this command from inside of the iframe.


Edit 1:just noticed now, that var divGptAdId = '%%PATTERN:url%%; will not return correct id of div on the page in #hash way, so now it's needed to give him a correct container div id change:

if(!divGptAdId) {
    return;
}

to

if(!divGptAdId) {
    divGptAdId = 'div-gpt-ad-container-div-id-1';
}

这篇关于Google DFP - 从内部调整 SafeFrame 自定义创意外部 iframe 容器的大小(展开广告)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 01:42