Javascript 如何在遵守不允许内联脚本的CSP的同时动态设置Google Universal Analytics的跟踪代码?

Javascript 如何在遵守不允许内联脚本的CSP的同时动态设置Google Universal Analytics的跟踪代码?,javascript,asp.net-mvc,google-analytics,universal-analytics,content-security-policy,Javascript,Asp.net Mvc,Google Analytics,Universal Analytics,Content Security Policy,我有一个网站解决方案,可以部署到多个不同的URL,每个URL都为不同的客户端打上品牌。部署过程在web.config、数据库等中设置各种特定于客户端的配置数据。所有客户端使用相同的网站代码,但不同的配置数据意味着每个客户端的网站外观和行为不同 我想在每个客户机的基础上设置一个跟踪代码。这是添加到每个页面的脚本块中出现的代码(以下示例中的“UA-12345678-1”): 然而,我正在使用(CSP)功能来锁定网站,作为这一功能的一部分,我禁用了内联脚本:所有脚本都必须从.js文件加载 因此,我创建

我有一个网站解决方案,可以部署到多个不同的URL,每个URL都为不同的客户端打上品牌。部署过程在web.config、数据库等中设置各种特定于客户端的配置数据。所有客户端使用相同的网站代码,但不同的配置数据意味着每个客户端的网站外观和行为不同

我想在每个客户机的基础上设置一个跟踪代码。这是添加到每个页面的脚本块中出现的代码(以下示例中的“UA-12345678-1”):

然而,我正在使用(CSP)功能来锁定网站,作为这一功能的一部分,我禁用了内联脚本:所有脚本都必须从.js文件加载

因此,我创建了一个JavaScript文件,其中包含上面脚本块的修改版本,我在HTML页面中引用了该版本:

(function (i, s, o, g, r, a, m) {
    i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', ga_token, 'auto');
ga('send', 'pageview');
我的计划是在这段脚本运行之前设置
ga_令牌
变量的值。我想我应该将变量值隐藏在HTML中的某个地方(在data-*属性中):

然而,由于执行的顺序,这被证明是很棘手的。根据谷歌的文档,脚本块应该放在HTML页面中的关闭标记
之前,虽然有一些奇特的东西在进行,所以在加载页面之前,它不会尝试实际执行任何操作,但是
ga('create',…
使用跟踪代码的调用实际上会立即执行。因此,
ga_令牌的值在使用之前不会设置

理论上,我可以将设置
ga_token
值的代码移动到Google脚本块的正上方,但这样做会在加载DOM之前执行该代码,在这种情况下,我可能无法获取所需的值。(我当然不能使用jQuery,因为我要到稍后才会加载jQuery库)


还有其他方法吗?

在完全加载DOM之前读取DOM是可以的,使用节点进行操作是有风险的。 因此,您的解决方案可以如下所示:

生成的HTML页面

你修改的分析加载器

var ga_token=document.getElementById(“serverData”).gaToken.value;
(功能(i、s、o、g、r、a、m){
i['GoogleAnalyticsObject']=r;i[r]=i[r]| |函数(){
(i[r].q=i[r].q | |[]).push(参数)},i[r].l=1*新日期();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(窗口,文档,“脚本”,“www.google-analytics.com/analytics.js”,“ga”);
ga(“创建”,ga_标记,“自动”);
ga(‘发送’、‘页面浏览’);

没有jQuery和
的另一个实现

<html id="dashboard" data-ga_id="{{ settings.GOOGLE_ANALYTICS_ACCOUNT }}">

谢谢。在发布我的问题之前,我确实尝试过这个方法,它确实有效,但我担心它可能只在某些时候有效。如果读取DOM总是可以的话,那就好了。(我将数据放在
HTML
标记的ID属性中,以确保它确实已加载:-).完全是新手问题,但有人能解释一下这是如何围绕CSP预防工作的吗?
(function (i, s, o, g, r, a, m) {
    i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', ga_token, 'auto');
ga('send', 'pageview');
<div id="ga-token-data" data-ga-token="@ViewBag.GoogleAnalyticsToken">
$(document).ready(function () {
    ga_token = $("#ga-token-data").data("ga-token");
})
<form id="serverData">
    <input type="hidden" name="gaToken" value="@ViewBag.GoogleAnalyticsToken" />
</form>
<script>
var ga_token = document.getElementById("serverData").gaToken.value;
(function (i, s, o, g, r, a, m) {
    i['GoogleAnalyticsObject'] = r; i[r] = i[r] || function () {
          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

ga('create', ga_token, 'auto');
ga('send', 'pageview');
</script>
<html id="dashboard" data-ga_id="{{ settings.GOOGLE_ANALYTICS_ACCOUNT }}">
var ga_id = document.getElementById("push-dashboard").dataset.ga_id;

if (ga_id) {
    (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
    })(window,document,'script','//www.google-analytics.com/analytics.js,'ga');

    ga('create', ga_id, 'auto');
    ga('send', 'pageview');
}