Google DFP - 从内部调整 SafeFrame 自定义广告素材外部 Iframe 容器的大小(展开广告)

2023-12-24

我正在寻找解决方案,可以从 Google DFP 广告管理系统的自定义广告素材内部扩展 SafeFrame 自定义广告,这是否可能?


有两种可能的解决方案:

1)使用SafeFrame API

pros:

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

cons:

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

2)编写你自己的APIwindow.postMessage()JavaScript 方法

cons:

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

pros:

  • 您可以通过您的创意对您的网站执行几乎任何操作

1)使用SafeFrame API

这个API比较容易使用,你可以看一些例子GPT Safeframe 预览工具 http://publisherconsole.appspot.com/safeframe/creative-preview.html.

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

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

这将允许在您的网站上扩展 SafeFrame 广告。有关此内容的更多信息,请参见通过 GPT 控制 SafeFrame 容器行为 https://support.google.com/dfp_premium/answer/4578089?hl=en.

现在您可以创建自定义广告素材并将其作为 SafeFrame 在您的网站上提供。这是我的一个例子。这个例子可以“等待”直到它可见,然后将扩展到高度<div id="container">这是 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. 编写你自己的APIwindow.postMessage()JavaScript 方法

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

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

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

<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 内部更改网站上的任何内容时,您可以在您的 网站并从 iframe 内部调用此命令。


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

if(!divGptAdId) {
    return;
}

to

if(!divGptAdId) { 
    divGptAdId = 'div-gpt-ad-container-div-id-1';
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Google DFP - 从内部调整 SafeFrame 自定义广告素材外部 Iframe 容器的大小(展开广告) 的相关文章

  • 如何将 blob 文件附加到 HTML href="mailto:" 中

    我有一个可通过 URL 获取的文件 需要授权 我创建了一个 mailto 链接 并希望将此文件附加到邮件中 我怎样才能做到这一点 类似于 mailto 电子邮件受保护 cdn cgi l email protection attachmen
  • 从 json 数组中获取成对的值

    首先 这是我从 php 源获取的 json 值 oid 2 cid 107 oid 4 cid 98 oid 4 cid 99 之后 我想要得到并且oid值以及相应的cid值例如 oid 2 and cid 107一口气 oid 4 and
  • 谷歌脚本循环性能

    我是 google 脚本的新手 我不确定为什么与 Excel VBA 的简单循环相比 我的性能如此差 我附上了下面的代码 它是一个大约 1200 行的循环 每秒删除大约 2 3 行 我写的脚本效率很低吗 我还不熟悉 Javascript 但
  • model.save() 返回无效输出

    我正在使用本文中的 Node js mongodb 和express 对 REST Api 进行简单测试 MERN 第一部分 使用 Node js 和 Express 构建 RESTful API https medium com week
  • nuxt如何访问javascript文件中的env

    我无法在 nuxt 2 15 之外访问我的环境变量 当我部署时我可以看到 nuxt context config在浏览器中有正确的变量 但在自定义js文件中我无法访问process env baseURL它返回未定义 nuxt config
  • iOS Javascript DOM“冻结?”

    这里有几个问题 有没有办法阻止 iOS 在滚动时冻结页面上的 javascript 当您在另一个选项卡中或切换应用程序时 iOS 是否会冻结 JavaScript iOS 上还有其他主要的 javascript 限制吗 iOS 6 x 会暂
  • 引发一系列事件 Backbone event:name

    extend object Backbone Events object on myalert one function msg document body innerHTML eve1 msg msg name this name con
  • 为什么这个 JavaScript 可以在 Safari 上运行,但不能在 Firefox 上运行?

    我有 HTML 文件 我在 Safari 上尝试了该代码 运行良好 但是当我在 Firefox 上尝试这个时 它不起作用 任何人都可以建议如何使其在 Firefox 上工作吗 单击撤消按钮时 我想从 jsp 文件中检索内容 当我在 mac
  • 如何在html中创建字体选择栏

    我想创建一个下拉菜单 在其中我们可以看到所有可用的字体 并且可以选择我们选择的任何字体 我还想创建一个字体颜色选择小部件 存在大量的字体样式 我想知道如何获取所有这些字体以及如何创建一个小部件 用户可以使用该小部件选择他选择的颜色 为了创建
  • Google App Script postMessage 与收件人窗口的来源不匹配

    我有一个 Google App 脚本部署为Web应用程序 https developers google com apps script guides web 它工作正常 直到今天晚上我发现它无法在 Firefox 或 Chrome 中加载
  • CKEDITOR.styleSet.add - 'a' 元素的新样式

    由于某种原因如果我改变 p to a 它不再出现在样式列表中 有什么理由吗 CKEDITOR stylesSet add default name Wys wiersza 1 element p styles line height 18p
  • 我可以阻止history.popstate在初始页面加载时触发吗?

    我正在开发一个通过 AJAX 提供内容的网站 如果您单击菜单中的某个项目 内容 div 会更新为 get回应 没什么花哨的 我正在实施history pushState允许使用浏览器的后退 前进按钮进行导航 我有以下内容可以在历史导航上加载
  • 名称属性的 CSS 选择器?

    这可能是一个愚蠢的问题 但是属性的 CSS 选择器是什么 a 那是 名字 document body innerHTML myString anchor HTML String 这段 JavaScript 创建了一个 a 带有名称的元素 H
  • Javascript for 循环跳过最后一个元素

    我有一个数组 根据某些条件从中删除某些元素 当我删除元素时 我会重新启动 for 循环 因为索引已刷新 var k for k 0 k lt this j data length k if condition true this j dat
  • 从变量值动态设置 ng-controller

    我正在使用 AngularJs 和 NodeJS 开发一个应用程序 我对将控制器的名称设置为主控制器中的变量的值感到震惊 为了更好地解释它 我的 index html 看起来像这样 tbody tr td td td member task
  • Angular2 - 防止复选框被选中

    我有一个每行包含一个复选框的表 在表头中 我有一个Check All切换所有表格行框的复选框 我正在尝试实现一些逻辑 如果复选框的数量将超过特定限制 则显示错误并且不切换表行复选框或checkall盒子本身 有一个问题允许checkAll即
  • 特别更改画布上的笔画不透明度,但不更改颜色

    我有一个漂亮整洁的脚本 可以循环显示颜色 并且与 xxxxxx格式 但我想改变透明度 有没有办法做到这一点 我指的是ctx strokeStyle 这是当前的代码 canvas strokeStyle 16777215 s length i
  • 谷歌绘制具有相同比例的多个系列的图表

    我正在寻找一种在图形上显示多个系列的方法 这些系列具有相同的比例但仅显示一次 正如你在这里看到的 http jsfiddle net Youkoal d3xwnqdu http jsfiddle net Youkoal d3xwnqdu 我
  • Electron 应用程序中的 NEDB 持久化

    我正在尝试从电子应用程序连接到 nedb CRUD 操作效果很好 但我没有看到 db 文件 D my db 检查隐藏文件 文件存在于某个地方 因为即使在机器重新启动后它也会保留数据 我怀疑电子威胁着我的相对路径 但我可以在任何地方找到它 v
  • 如何运行 Mike Bostock 的 D3 示例?

    我一直在尝试经营迈克博斯托克透视地球仪 http bl ocks org mbostock 6747043例如 但是如果您尝试在本地重现它 则对其 json 文件的引用是不正确的 问题来自于这行代码 d3 json mbostock raw

随机推荐

  • 在Lua中,我可以轻松地选择第N个结果而不需要自定义函数吗?

    假设我将一个字符串插入到表中 如下所示 table insert tbl mystring 然后mystring通过将所有出现的 a 替换为 b 生成input mystring string gsub input a b 将两者合并为一个
  • 使用 JSON.NET 序列化/反序列化动态属性名称

    我有以下课程 public class MyRequest public string Type get set public string Source get set 我想序列化 反序列化以下值Source来自名为值的 JSON 字段T
  • java使用excel打开csv文件

    我正在为大学做一个项目 并制作了一个创建 csv 文件的程序 我希望有一个按钮 您可以单击该按钮 然后使用 Excel 打开 csv 文件 谢谢 知道系统上安装了 MsOffice 您应该能够使用以下命令从命令行打开文档 excel myD
  • Keycloak.loadUserProfile() 上的 Keycloak 403(禁止)

    我是 Keycloak 的新手 我尝试使用以下代码获取用户信息 keycloakAuth loadUserProfile success function profile debugger console log profile error
  • InvalidOperationException:无法为“角色”创建 DbSet,因为该类型未包含在上下文的模型中

    以下解决方案在 net core 1 1中有效 但从1 1升级到2 0后 我收到以下错误 InvalidOperationException 无法为 Role 创建 DbSet 因为该类型未包含在上下文的模型中 当用户尝试登录时 执行以下语
  • 捕获谷歌应用程序引擎日志输出

    如何在管理控制台之外查看 Google App Engine 日志 我正在开发 所以使用dev appserver py 管理控制台并希望在发出记录时查看日志 我想使用标准 Unix 工具 例如 在控制台中监控日志输出 less grep
  • 查找文件中最后一次出现的字符串

    我需要从 C 中的特定字符串中获取最后一次出现的日志跟踪 例如 lines File ReadLines logPath SkipWhile line gt line Contains param Take 20 该代码可以工作 但它从日志
  • Coffeescript 中的臃肿 JS 想要返回所有内容

    我这里有这个 Coffeescript brew args gt for e in args alert e null brew fo re eo 我希望我不需要在那里放置 null 来让它工作 但可惜的是 它编译成这样 brew func
  • 比较 Pyspark 中的列

    我正在开发一个包含 n 列的 PySpark DataFrame 我有一组 m 列 m 例如 输入 PySpark DataFrame 包含 col 1 1 2 3 col 2 2 1 4 col 3 3 2 5 Ouput col 4 m
  • 如何将 git note 移动到不同的提交?

    我已经错误地记录了错误的提交 有没有一种简单的方法可以将其整体移动到不同的提交 我希望有一种方法可以在语义上将注释重新定位到不同的提交上 但是无论什么是最简单的都会很高兴知道 我怀疑最简单的选择是使用桌面剪贴板复制粘贴文本 可能最简单的方法
  • 等宽窗扇

    我的应用程序有一个带有两个孩子的 SashForm 我希望在调整窗口大小时左孩子保持相同的大小 我想要 Eclipse 对 Package Explorer 和主编辑器做同样的事情 当您调整窗口大小时 只有文本编辑器会更改大小 但是 Pac
  • Django 子查询和带有 OuterRef 的注释

    我在使用 annotate 时遇到问题OuterRef在 Django 1 11 中的子查询 型号示例 class A models Model name models CharField max length 50 class B mod
  • IIS Express 与 VS2010 SP1 不断重建网站

    我正在使用具有多个网站项目的大型解决方案 最近决定从 Cassini 切换到 IIS Express 大约有 10 名左右的开发人员共享相同的解决方案 项目以及 web configs 除了我之外 他们都在愉快地使用 IIS Express
  • Nougat 版本的快捷方式

    当我尝试在 Intent 包中传递可序列化时 我发现了这个致命异常 我认为这与我试图实现的牛轧糖快捷方式有关 这里有一个例外 12 16 16 17 32 972 20461 20461 debug E AndroidRuntime FAT
  • Flutter 蓝牙打印到 Zebra

    我需要在 Zebra zq520 蓝牙热敏打印机上添加打印功能 我设法使用 flutter blue 插件来做到这一点 但我对实现并不满意 我讨厌将字符串分成更小的块以便通过蓝牙 并且等待 我想知道是否有更好的方法 就像我们在过去的 好 j
  • 通过套接字发送对象

    我过去做过的唯一套接字编程是简单的文本流 我想知道通过套接字发送 Java 对象之类的内容的最有效方法是什么 例如 如果我有以下 Employee 类 Dependent 将是一个由家属信息组成的简单类 public class Emplo
  • 如何禁用 esLint 上的缩进检查?

    缩进规则似乎无法禁用 如何 在配置设置中 禁用此规则 谢谢 将规则设置为 off 在你的配置中像这样 rules indent off 您可以阅读更多内容这里的文档 https eslint org docs user guide conf
  • 即使文件大小不是 0 字节,filesize() 也始终读取 0 字节

    我在下面编写了一些代码 目前我正在测试 因此代码中没有数据库查询 下面的代码说的是if filesize filename 0 总是去else即使文件不是 0 字节并且其中有 16 字节数据 我一无所获 它似乎总是认为文件是 0 字节 我认
  • 如何在 Laravel 中模拟 DB 门面?

    我正在编写单元测试 默认情况下它们不应访问数据库 按照一般规则 我总是使用 eloquent 来获取结果 但一些更复杂的查询我必须使用原始数据库 我有这个功能 public function GetPassword email result
  • Google DFP - 从内部调整 SafeFrame 自定义广告素材外部 Iframe 容器的大小(展开广告)

    我正在寻找解决方案 可以从 Google DFP 广告管理系统的自定义广告素材内部扩展 SafeFrame 自定义广告 这是否可能 有两种可能的解决方案 1 使用SafeFrame API pros 你可以 开箱即用 使用它 您可以在任何网