javascript - 在 AngularJS View 中的移动网络中显示原生广告时出现问题

标签 javascript html angularjs facebook-audience-network

在我的 AngularJS 应用程序中,我尝试将 Facebook 原生网络广告添加到我的 View 之一。我按照in the documentation概述的步骤进行操作生成必要的 HTML 片段并将其添加到我的 View 中。

我的应用程序正在使用 ui-router 来解析路由。当访问包含此代码片段的路由/ View 时,不会显示 FB 广告,也不会调用任何回调(onAdLoaded 或 onAdError)。

Facebook 生成的 HTML 片段(添加到 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 a = 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 i = 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';
            for (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>

我注意到 Facebook Audience Network JS 是异步加载的,并怀疑我可能存在导致问题的竞争条件。

<script type="text/javascript" src="https://connect.facebook.net/en_US/fbadnw.js" async></script>

为了测试这一点,我已将 FB 代码片段移出我的 View 并移至我的 SPA index.html 中。广告按预期显示。加载脚本后,fbadnw.js 脚本会调用什么回调? FB 生成的代码中的闭包是否在加载 fbadnw.js 之前被调用?

index.html(有效)

    <!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 a = 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 i = 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';
                    for (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>

最佳答案

我通过编辑 FB 提供的样板代码解决了这个问题。简而言之,所提供的闭包(缩小的)尝试:

  1. 找到将在其中呈现广告的 iframe 元素并将其设置为 src 和其他属性。
  2. 附加一个事件处理程序来监听发布消息“message”。
  3. 使用 FB Audience Network (ADNW.init()) 初始化广告

我的问题在于该代码在步骤 1 中所做的假设。

var b = d.currentScript || (function() {
    var c = d.getElementsByTagName('script');
    return c[c.length - 1];
})();
var e = b.parentElement;

上面的代码试图找到这个DIV。

<div style="display:none; position: relative;">

它首先尝试找到页面上最后一个脚本元素的父元素来实现此目的。这很脆弱,就我而言,不起作用。我的文档中添加的最后一个脚本元素不是此代码所期望的。

我修改了此代码以通过 ID 显式选择正确的元素。

添加了一个 ID 来包含 DIV:

<div id="fb-ad-container" style="display:none; position: relative;">

简化 DOM 解析代码(步骤 1)以通过 ID 选择此 DIV:

 var e = d.getElementById("fb-ad-container");

通过按 ID 选择正确的元素,我能够减少定位当前脚本元素的需要。脚本的其余部分按预期运行。

关于javascript - 在 AngularJS View 中的移动网络中显示原生广告时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39458776/

相关文章:

angularjs - 如何在 URL 中排序过滤器而不将它们放在键值中

javascript - 如何测试缩小后的文件?

javascript - 如何使用 gantt-tooltip 属性在 Angular 表中以用户输入的格式显示日期

javascript - 从 Chrome 扩展程序注入(inject)的脚本是否可以访问页面上的 javascript (angularjs)?

html - 为什么我的 XPath 不基于 text() 进行选择?

javascript - 为什么 jQuery .addClass() 比直接修改 HTML 更有用

html - css BEM概念

Javascript 格式化表格单元格中的空值

javascript - node.js express-session 是无状态的还是有状态的?

javascript - 组件在更新时消失