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

IT技术 javascript dom google-chrome-extension google-analytics content-script
2021-01-18 16:00:18

我正在通过我的 chrome 扩展向页面末尾添加一些外部 JavaScript。然后外部 JavaScript 尝试将一些数据发送回服务器,但是这并没有发生。

JavaScript 想要获取当前页面的 url 和引用者并将其发送回服务器。

任何人都可以请教我这里出了什么问题,如果不可能,我如何才能将当前页面的数据发布回服务器。

清单文件.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个回答

内容脚本不在页面范围内运行(另请参阅),它们在扩展程序和网页之间的上下文中运行。

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

有两(三)种方法可以修复它。

  1. 使用此方法注入您的代码(如问题中所述)不鼓励将这种方法用于您的目的,因为您的脚本会覆盖常用的全局变量。使用此方法实现您的脚本将破坏许多网站上的跟踪 -不要使用它
  2. 在内容脚本的范围内完全运行代码:
    两个选项:
    1. 在扩展中包含外部文件
    2. 在扩展中包含外部文件,并实现自动更新功能。

方法一:完全本地复制

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,则必须使用复杂的代码注入方式,因为无法从外部 URL 包含内容脚本

此答案的旧版本依赖于背景页面,chrome.tabs.executeScript为此目的,但自 Chrome 20 以来,已提供更好的方法:使用chrome.storageAPI 缓存 JavaScript 代码。为了保持代码更新,我将在存储中存储一个“上次更新”时间戳;您也可以改用chrome.alarmsAPI。

注意:不要忘记在您的扩展程序中包含外部文件的本地副本,以防用户没有互联网连接等。 如果没有互联网连接,Google Analytics 无论如何都无法工作。

内容脚本,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.
让它工作了,但是奇怪的是,谷歌分析没有跟踪用户访问了哪些网站,也没有跟踪用户在网络上的位置的其他数据。另外,有没有办法知道用户何时打开/关闭选项卡或窗口?
2021-03-24 16:00:18
嗨,这听起来很棒,但我面临的问题是它仍然没有跟踪用户正在浏览的页面。它无法将任何数据发布回谷歌的服务器。你能帮我弄清楚我做错了什么吗?我已经使用了你给我的代码。顺便说一句,感谢您帮助我复习关于这个主题的知识,虽然从 google 的文档中似乎很容易理解,但我并没有真正找到它。我对此表示赞同,我会尝试几次以解决我可能出错的问题。
2021-03-26 16:00:18
@galambalazs 更新了我的答案以包含该功能。
2021-03-27 16:00:18
@user658911 将事件侦听器绑定到chrome.tabs.onRemoved. 关于跟踪:我的演示效果很好。您是否有任何其他将事件侦听器绑定到的后台脚本chrome.extension.onRequest
2021-04-05 16:00:18
我很抱歉,但我必须反对这一点,因为建议的方法将他锁定在 ga.js 的静态版本中。它阻止他获取更新,因此它应该由谷歌提供服务。看官方推荐:support.google.com/googleanalytics/bin/...
2021-04-10 16:00:18

2015年更新

新的Universal Analytics代码段绝对可以处理多个跟踪器,因此假设您为自己的跟踪器指定一个唯一名称并在页面上下文中运行所有Analytics 代码,那么您应该很高兴。

// 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而不是第一个<script>元素。这是因为 google 假设您在内联脚本块中添加分析,而在这里您从内容脚本中添加它。

我已经尝试了上面的所有答案,但这是唯一按预期工作的答案。
2021-03-15 16:00:18
在我找到这篇文章之前,我已经崩溃了。谢谢你,兄弟!!!!现在我的内容脚本被跟踪了!
2021-03-27 16:00:18

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

你可以参考这个扩展作为参考:https : //github.com/GoogleChrome/chrome-app-samples/tree/master/samples/analytics它使用这个库:https : //github.com/GoogleChrome/chrome-平台分析

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

  <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;
这是我找到的最好的答案。在您共享的这个包的帮助下开始工作非常简单。谢谢@awongh
2021-03-17 16:00:18