javascript - Trouble displaying Native Ads in Mobile Web in AngularJS view -
in angularjs application attempting add facebook native web ad 1 of views. followed steps outlined in documentation generate necessary html snippet , added view.
my application using ui-router resolve routes. when visiting route/view containing code snippet fb ad not displayed , neither of callbacks invoked (onadloaded or onaderror).
facebook generated html snippet (added view):
<div style="display:none; position: relative;"> <iframe style="display:none;"></iframe> <script type="text/javascript"> var data = { placementid: 'xxxxxxxxxxx_xxxxxxxx', format: 'native', testmode: true, onadloaded: function (element) { console.log('audience network ad loaded'); element.style.display = 'block'; }, onaderror: function (errorcode, errormessage) { console.log('audience network error (' + errorcode + ') ' + errormessage); } }; (function (w, l, d, t) { var = t(); var b = d.currentscript || (function () { var c = d.getelementsbytagname('script'); return c[c.length - 1]; })(); var e = b.parentelement; e.dataset.placementid = data.placementid; var f = function (v) { try { return v.document.referrer; } catch (e) { } return ''; }; var g = function (h) { var = h.indexof('/', h.indexof('://') + 3); if (i === -1) { return h; } return h.substring(0, i); }; var j = [l.href]; var k = false; var m = false; if (w !== w.parent) { var n; var o = w; while (o !== n) { var h; try { m = m || (o.$sf && o.$sf.ext); h = o.location.href; } catch (e) { k = true; } j.push(h || f(n)); n = o; o = o.parent; } } var p = l.ancestororigins; if (p) { if (p.length > 0) { data.domain = p[p.length - 1]; } else { data.domain = g(j[j.length - 1]); } } data.url = j[j.length - 1]; data.channel = g(j[0]); data.width = screen.width; data.height = screen.height; data.pixelratio = w.devicepixelratio; data.placementindex = w.adnw && w.adnw.ads ? w.adnw.ads.length : 0; data.crossdomain = k; data.safeframe = !!m; var q = {}; q.iframe = e.firstelementchild; var r = 'https://www.facebook.com/audiencenetwork/web/?sdk=5.3'; (var s in data) { q[s] = data[s]; if (typeof(data[s]) !== 'function') { r += '&' + s + '=' + encodeuricomponent(data[s]); } } q.iframe.src = r; q.tagjsinittime = a; q.rootelement = e; q.events = []; w.addeventlistener('message', function (u) { if (u.source !== q.iframe.contentwindow) { return; } u.data.receivedtimestamp = t(); if (this.sdkeventhandler) { this.sdkeventhandler(u.data); } else { this.events.push(u.data); } }.bind(q), false); q.tagjsiframeappendedtime = t(); w.adnw = w.adnw || {}; w.adnw.ads = w.adnw.ads || []; w.adnw.ads.push(q); w.adnw.init && w.adnw.init(q); })(window, location, document, date.now || function () { return +new date; }); </script> <script type="text/javascript" src="https://connect.facebook.net/en_us/fbadnw.js" async></script> <style> .thirdpartyroot { background-color: white; color: #444; border: 1px solid #ccc; border-left: 0; border-right: 0; font-family: sans-serif; font-size: 14px; line-height: 16px; width: 320px; text-align: left; position: relative; } .thirdpartymediaclass { width: 320px; height: 168px; margin: 12px 0; } .thirdpartysubtitleclass { font-size: 18px; -webkit-line-clamp: 1; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; height: 16px; -webkit-box-orient: vertical; } .thirdpartytitleclass { padding-right: 12px; line-height: 18px; -webkit-line-clamp: 2; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; height: 36px; -webkit-box-orient: vertical; } .thirdpartycalltoactionclass { background-color: #416bc4; color: white; border-radius: 4px; padding: 6px 20px; float: right; text-align: center; text-transform: uppercase; font-size: 11px; } .fbdefaultnativeadwrapper { font-size: 12px; line-height: 14px; margin: 12px 0; height: 36px; vertical-align: top; } </style> <div class="thirdpartyroot"> <a class="fbadlink"> <div class="fbadmedia thirdpartymediaclass"></div> <div class="fbadsubtitle thirdpartysubtitleclass"></div> <div class="fbdefaultnativeadwrapper"> <div class="fbadcalltoaction thirdpartycalltoactionclass"></div> <div class="fbadtitle thirdpartytitleclass"></div> </div> </a> </div> </div>
i noticed facebook audience network js loaded asynchronously , suspected might have race condition causing issue.
<script type="text/javascript" src="https://connect.facebook.net/en_us/fbadnw.js" async></script>
to test this, i've moved fb code snippet out of view , spa index.html. ad appears expected. callback fbadnw.js script call once script loaded? closure within fb generated code being invoked before fbadnw.js loaded perhaps?
index.html (works)
<!doctype html> <html ng-app="kcl-app"> <head> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title ng-bind="pagetitle"></title> </head> <body> <!-- ui-router view --> <div ui-view></div> <!-- fb begin --> <div class="fb-native"> <div style="display:none; position: relative;"> <iframe style="display:none;"></iframe> <script type="text/javascript"> var data = { placementid: 'xxxxxxxxxxx_xxxxxxxx', format: 'native', testmode: true, onadloaded: function (element) { console.log('audience network ad loaded'); element.style.display = 'block'; }, onaderror: function (errorcode, errormessage) { console.log('audience network error (' + errorcode + ') ' + errormessage); } }; (function (w, l, d, t) { var = t(); var b = d.currentscript || (function () { var c = d.getelementsbytagname('script'); return c[c.length - 1]; })(); var e = b.parentelement; e.dataset.placementid = data.placementid; var f = function (v) { try { return v.document.referrer; } catch (e) { } return ''; }; var g = function (h) { var = h.indexof('/', h.indexof('://') + 3); if (i === -1) { return h; } return h.substring(0, i); }; var j = [l.href]; var k = false; var m = false; if (w !== w.parent) { var n; var o = w; while (o !== n) { var h; try { m = m || (o.$sf && o.$sf.ext); h = o.location.href; } catch (e) { k = true; } j.push(h || f(n)); n = o; o = o.parent; } } var p = l.ancestororigins; if (p) { if (p.length > 0) { data.domain = p[p.length - 1]; } else { data.domain = g(j[j.length - 1]); } } data.url = j[j.length - 1]; data.channel = g(j[0]); data.width = screen.width; data.height = screen.height; data.pixelratio = w.devicepixelratio; data.placementindex = w.adnw && w.adnw.ads ? w.adnw.ads.length : 0; data.crossdomain = k; data.safeframe = !!m; var q = {}; q.iframe = e.firstelementchild; var r = 'https://www.facebook.com/audiencenetwork/web/?sdk=5.3'; (var s in data) { q[s] = data[s]; if (typeof(data[s]) !== 'function') { r += '&' + s + '=' + encodeuricomponent(data[s]); } } q.iframe.src = r; q.tagjsinittime = a; q.rootelement = e; q.events = []; w.addeventlistener('message', function (u) { if (u.source !== q.iframe.contentwindow) { return; } u.data.receivedtimestamp = t(); if (this.sdkeventhandler) { this.sdkeventhandler(u.data); } else { this.events.push(u.data); } }.bind(q), false); q.tagjsiframeappendedtime = t(); w.adnw = w.adnw || {}; w.adnw.ads = w.adnw.ads || []; w.adnw.ads.push(q); w.adnw.init && w.adnw.init(q); })(window, location, document, date.now || function () { return +new date; }); </script> <script type="text/javascript" src="https://connect.facebook.net/en_us/fbadnw.js" async></script> <style> .thirdpartyroot { background-color: white; color: #444; border: 1px solid #ccc; border-left: 0; border-right: 0; font-family: sans-serif; font-size: 14px; line-height: 16px; width: 320px; text-align: left; position: relative; } .thirdpartymediaclass { width: 320px; height: 168px; margin: 12px 0; } .thirdpartysubtitleclass { font-size: 18px; -webkit-line-clamp: 1; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; height: 16px; -webkit-box-orient: vertical; } .thirdpartytitleclass { padding-right: 12px; line-height: 18px; -webkit-line-clamp: 2; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; height: 36px; -webkit-box-orient: vertical; } .thirdpartycalltoactionclass { background-color: #416bc4; color: white; border-radius: 4px; padding: 6px 20px; float: right; text-align: center; text-transform: uppercase; font-size: 11px; } .fbdefaultnativeadwrapper { font-size: 12px; line-height: 14px; margin: 12px 0; height: 36px; vertical-align: top; } </style> <div class="thirdpartyroot"> <a class="fbadlink"> <div class="fbadmedia thirdpartymediaclass"></div> <div class="fbadsubtitle thirdpartysubtitleclass"></div> <div class="fbdefaultnativeadwrapper"> <div class="fbadcalltoaction thirdpartycalltoactionclass"></div> <div class="fbadtitle thirdpartytitleclass"></div> </div> </a> </div> </div> </div> <!-- fb end --> </body> </html>
i able resolve issue editing boilerplate code provided fb. in nutshell, provided closure (minified) attempts to:
- locate iframe element ad rendered , set it's src , other attributes.
- attach event handler listen post messages "message".
- initialize ad fb audience network (adnw.init())
my problem assumptions code makes in step 1.
var b = d.currentscript || (function() { var c = d.getelementsbytagname('script'); return c[c.length - 1]; })(); var e = b.parentelement;
the above code attempting locate div.
<div style="display:none; position: relative;">
it first trying locate parent of last script element on page. brittle and, in case, did not work. last script element added in document not 1 code expected.
i modified code explicitly select correct element id.
added id containing div:
<div id="fb-ad-container" style="display:none; position: relative;">
simplify dom parsing code (step 1) select div id:
var e = d.getelementbyid("fb-ad-container");
by selecting correct element id able alleviate need locate current script element. rest of script ran expected.
Comments
Post a Comment