javascript - Google DFP - Resize SafeFrame custom creative outer Iframe container from inside (expand ad) -
i'm searching solution, can expand safeframe custom ad inside of custom creative in google dfp, possible somehow?
there 2 possible solutions:
1) using safeframe api
pros:
- u can use "out of box"
- you can use on website, no custom code on website needed
- it's safe use
cons:
- it's limited fill visible area of website
- need wait, until ad unit visible user
2) code own api window.postmessage()
javascript method
cons:
- you need add custom code website
- it's possible threat, if use 3th party creatives
pros:
- you can website creative
1) using safeframe api
this api realatively easy use, can see examples in gpt safeframe preview tool.
first need update dfp initialization script in <head>
of website
var pageconfig = { allowoverlayexpansion: true, allowpushexpansion: true, sandbox: true }; googletag.pubads().setsafeframeconfig(pageconfig);
this allow expand safeframe ads on website. more in control safeframe container behavior through gpt.
now can create custom creative , serve safeframe on website. here 1 example. example can "wait" util it's visible, , expand height of <div id="container">
inside of safeframe:
<div id="container"> lines 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 var expanded = false; function expand() { var self= $sf.ext.geom().self; var config = { push: true, // want push expanded content b: 0 }; var el = document.getelementbyid('container'); var containerheight = el.offsetheight; // height bottom, need expanded var expandbottom = containerheight - self.h; // if container whole inside safeframe, not expand if(expandbottom < 0) return; config.b = expandbottom; $sf.ext.expand(config); } function expanddelayed(forceexpand) { // expand run once, or can force run again // collapse first needed if(expanded && forceexpand || !expanded) { $sf.ext.collapse(); expanded = false; // there must timeout, because .collapse(); method deplayed somehow settimeout(expand, 0); } } $sf.ext.register(160, 150, function(status, data) { // code whole magic of "waiting" right moment if (status === 'geom-update') { expanddelayed(); } // change global expanded status if (status === 'expanded') { expanded = true; } }); // init expanddelayed(); </script>
2. code own api window.postmessage()
javascript method
first, need put code, dfp initialization script in <head>
of website. code add id of ad slot #hash-tag
<iframe>
's src can inside of 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 10 milliseconds, because iframe not yet rendered // , limited max 10 seconds wait var timeoutfunction = function () { var src = "#" + containerid; // `src` attribute null, when iframe friendlyiframe, , // when it's present, 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, need add code website, better separated .js file.
function onmessagereceivedgetstyle(e) { // filter setstyle commands 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 id, don't use jquery var elementid = e.data.id.replace(/#/, ""); var wrapperel = document.getelementbyid(elementid); if (wrapperel === null) { return; } var elements = [wrapperel]; // can target child elements 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 custom code in custom type of creative in dfp. here example, similar in first example, here script can wait until content , image loaded , expand/shrink iframe creative:
<div id="container"> <a href="#" target="_blank"> <img src="%%file:jpg1%%"> </a> <a href="#" target="_blank"> <img src="%%file:jpg2%%"> </a> </div> <style> { 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; } // id of ad unit <div> 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 fullwidth, , height height of container inside creative var width = '100%'; var height = container.offsetheight + 'px'; // send our request website window.top.postmessage({ cmd: 'setstyle', id: divgptadid, query: 'div, iframe', // want target child div , iframe , don't change container styles params: { display: 'block', height: height, width: width } }, '*'); } document.onreadystatechange = function () { // resize iframe when loaded if (document.readystate == "complete") { resizeoutsidesafeframe(); } }; // first resize must occur little bit later settimeout(resizeoutsidesafeframe, 100); </script>
that's all. when want change on website inside of iframe, can code own cmd on website , call command inside of iframe.
Comments
Post a Comment