Chrome扩展程序将外部JavaScript添加到当前页面的HTML

时间:2012-04-23 18:10:07

标签: javascript dom google-chrome-extension google-analytics content-script

我通过Chrome扩展程序在页面末尾添加了一些外部JavaScript。然后外部JavaScript尝试将一些数据发布回服务器,但是没有发生。

JavaScript希望获取当前页面和引荐来源的网址并将其发回服务器。

任何人都可以告诉我这里有什么问题,如果不可能,我怎样才能将数据从当前页面发布回服务器。

的manifest.json

{
  "name": "Website Safety",
  "version": "1.0",
  "manifest_version": 2,
  "description": "The Website Safety Extension.",
  "browser_action": {
    "name": "View the website information for ",
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": [
    "tabs", "http://*/*", "https://*/*"
  ],
  "background": {
  //  "scripts": ["refresh.js"]
    "page": "background.html"
  },
  "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'",
  //"background_page": "background.html"

  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["contentScript.js"]
    }
  ]
}

现在是contentScript.js

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-31046309-1']);
_gaq.push(['_setAllowLinker', true]);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
//ga.src = 'https://ssl.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

var _Hasync= _Hasync|| [];
_Hasync.push(['Histats.start', '1,1342541,4,0,0,0,00000000']);
_Hasync.push(['Histats.fasi', '1']);
_Hasync.push(['Histats.track_hits', '']);
(function() {
var hs = document.createElement('script'); hs.type = 'text/javascript'; hs.async = true;
hs.src = ('http://s10.histats.com/js15_as.js');
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(hs);
})();

3 个答案:

答案 0 :(得分:42)

内容脚本在页面范围内运行(see also),它们在您的扩展程序和网页之间的上下文中运行。

由于跟踪器属于“注入脚本”类型,因此这些跟踪器完全在网页的上下文中运行。但_gaqHasync变量却没有。因此,跟踪脚本无法读取配置变量。

有两种方法可以解决它。

  1. 使用this method注入您的代码(在问题中发布)。使用此方法不鼓励,因为您的脚本会覆盖常用的全局变量。使用此方法实施脚本将打破许多网站上的跟踪 - 不要使用
  2. 在内容脚本范围内完全运行代码:
    两种选择:
    1. 在扩展程序
    2. 中包含外部文件
    3. 在扩展程序中包含外部文件,并实现自动更新功能。
  3. 方法1:完全本地复制

    manifest.json (仅显示相关部分):

    {
      "name": "Website Safety",
      "version": "1.0",
      "manifest_version": 2,
      "description": "The Website Safety Extension.",
      "permissions": [
        "tabs", "http://*/*", "https://*/*"
      ],
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["ga-config.js", "ga.js", "js15_as.js"]
        }
      ]
    }
    

    ga-config.js 中,按以下方式定义变量:

    var _gaq = _gaq || [];
    _gaq.push(['_setAccount', 'UA-31046309-1']);
    _gaq.push(['_setAllowLinker', true]);
    _gaq.push(['_trackPageview']);
    
    var _Hasync= _Hasync|| [];
    _Hasync.push(['Histats.start', '1,1342541,4,0,0,0,00000000']);
    _Hasync.push(['Histats.fasi', '1']);
    _Hasync.push(['Histats.track_hits', '']);
    

    下载https://ssl.google-analytics.com/ga.js,并将其另存为 ga.js 下载http://s10.histats.com/js15_as.js,并将其另存为 js15_as.js

    方法2:注入最新的GA

    如果您想拥有最新版本的GA,则必须使用一种令人费解的注入代码的方式,因为内容脚本不能包含在外部网址

    此答案的旧版本依赖于背景页面和chrome.tabs.executeScript用于此目的,但自Chrome 20以来,一种更好的方法可用:使用chrome.storage API缓存JavaScript代码。 为了保持代码更新,我将在存储中存储“最后更新”的时间戳;您也可以使用chrome.alarms API。

    注意:请勿忘记在扩展程序中包含外部文件的本地副本,以防用户没有互联网连接等。 没有互联网连接,Google无论如何,分析都无法发挥作用。

    内容脚本, activate-ga.js

    var UPDATE_INTERVAL = 2 * 60 * 60 * 1000; // Update after 2 hour
    
    // Retrieve GA from storage
    chrome.storage.local.get({
        lastUpdated: 0,
        code: ''
    }, function(items) {
        if (Date.now() - items.lastUpdated > UPDATE_INTERVAL) {
            // Get updated file, and if found, save it.
            get('https://ssl.google-analytics.com/ga.js', function(code) {
                if (!code) return;
                chrome.storage.local.set({lastUpdated: Date.now(), code: code});
            });
        }
        if (items.code) // Cached GA is available, use it
            execute(items.code);
        else // No cached version yet. Load from extension
            get(chrome.extension.getURL('ga.js'), execute);
    });
    
    // Typically run within a few milliseconds
    function execute(code) {
        try { window.eval(code); } catch (e) { console.error(e); }
        // Run the rest of your code.
        // If your extension depends on GA, initialize it from here.
        // ...
    }
    
    function get(url, callback) {
        var x = new XMLHttpRequest();
        x.onload = x.onerror = function() { callback(x.responseText); };
        x.open('GET', url);
        x.send();
    }
    

    最低清单文件:

    {
      "name": "Website Safety",
      "version": "1.0",
      "manifest_version": 2,
      "permissions": [
        "tabs", "http://*/*", "https://*/*"
      ],
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["activate-ga.js"]
        }
      ],
      "web_accessible_resources": ["ga.js"]
    }
    

    同样的方法可以用于其他跟踪器。最低权限要求:

    • https://ssl.google-analytics.com/ga.js ,因此应在权限部分添加。 https://*/*<all_urls>也足够了。
    • 可选 unlimitedStorage - 如果您想使用chrome.storage存储大量数据。

答案 1 :(得分:5)

我通读了这个主题:https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/yc-ouDqfMw0并发现有一个官方的chrome方法可以将分析脚本添加到页面中,而且它不在官方文档中。

您可以参考此扩展程序以供参考:https://github.com/GoogleChrome/chrome-app-samples/tree/master/analytics并使用此库:https://github.com/GoogleChrome/chrome-platform-analytics

基本上你手动在本地包含脚本:

  <script src="your_path/google-analytics-bundle.js"></script>
  <script src="main.js"></script>

然后你调用一些库函数:

var service, tracker, out;

function initAnalyticsConfig(config) {
  document.getElementById('settings-loading').hidden = true;
  document.getElementById('settings-loaded').hidden = false;

  var checkbox = document.getElementById('analytics');
  checkbox.checked = config.isTrackingPermitted();
  checkbox.onchange = function() {
    config.setTrackingPermitted(checkbox.checked);
  };
}

注意:显然,您 拥有退出功能https://github.com/GoogleChrome/chrome-platform-analytics/wiki#add-privacy-support-aka-opt-out

function startApp() {
  // Initialize the Analytics service object with the name of your app.
  service = analytics.getService('ice_cream_app');
  service.getConfig().addCallback(initAnalyticsConfig);

  // Get a Tracker using your Google Analytics app Tracking ID.
  tracker = service.getTracker('UA-XXXXX-X');

  // Record an "appView" each time the user launches your app or goes to a new
  // screen within the app.
  tracker.sendAppView('MainView');
}

window.onload = startApp;

答案 2 :(得分:4)

2015年更新

新的 Universal Analytics 代码段绝对可以处理multiple trackers,因此假设您为自己提供了一个唯一名称并运行所有分析代码in the page's context,你应该好好去。

onsubmit=""

请注意,在分析代码段中只有一点修改,即使用// add Universal Analytics to the page (could be made conditional) runFunctionInPageContext(function () { (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); a.async=1;a.src=g;document.documentElement.appendChild(a) })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); }); // all Google Analytics calls should use our tracker name // and be run inside the page's context runFunctionInPageContext(function () { ga('create', 'UA-12345-6', 'auto', {'name': 'myTracker'}); ga('myTracker.send', 'pageview'); // note the prefix }); // simple helper function function runFunctionInPageContext(fn) { var script = document.createElement('script'); script.textContent = '(' + fn.toString() + '());'; document.documentElement.appendChild(script); document.documentElement.removeChild(script); } 代替第一个document.documentElement元素。这是因为谷歌假设你在内联脚本块中添加分析,而在这里你从内容脚本添加它。