Chrome 扩展程序将外部 javascript 添加到当前页面的 html
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10285886/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chrome extension adding external javascript to current page's html
提问by Vish
I am adding some external JavaScript to the end of the page via my chrome extension. The external JavaScript then tries to post some data back to the server, however that is not taking place.
我正在通过我的 chrome 扩展向页面末尾添加一些外部 JavaScript。然后外部 JavaScript 会尝试将一些数据发送回服务器,但是这并没有发生。
The JavaScript wants to get the url of the current page and the referrer and post it back to the server.
JavaScript 想要获取当前页面的 url 和引用者,并将其发送回服务器。
Can anyone please advice me what is wrong here and how can I if not possible this way can I post data from the current page back to the server.
任何人都可以请教我这里出了什么问题,如果不可能,我如何将当前页面中的数据发布回服务器。
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"]
}
]
}
for now 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);
})();
回答by Rob W
Content scripts do notrun in the scope of the page (see also), they run in a context between your extension and the web page.
内容脚本不在页面范围内运行(另请参阅),它们在扩展程序和网页之间的上下文中运行。
Since the trackers are of the type "Injected script", these fully run in the context of the web page. But the _gaq
and Hasync
variables don't. As a result, the track scripts cannot read the configuration variables.
由于跟踪器属于“注入脚本”类型,因此它们完全在网页上下文中运行。但是_gaq
和Hasync
变量没有。因此,跟踪脚本无法读取配置变量。
There are two (three) ways to fix it.
有两(三)种方法可以修复它。
- Inject your code (as posted in the question) using this method. Using this method for your purpose is discouraged, because your script overwrites a commonly used global variable. Implementing your script using this method will breakthe tracking on many websites - do not use it.
- Fully run the code within the scope of a content script:
Two options:- Include the external files in the extension
- Include the external files in the extension, plus implement an auto-update feature.
- 使用此方法注入您的代码(如问题中所述)。不鼓励将这种方法用于您的目的,因为您的脚本会覆盖常用的全局变量。使用此方法实现您的脚本将破坏许多网站上的跟踪 -不要使用它。
- 在内容脚本范围内完全运行代码:
两个选项:- 在扩展中包含外部文件
- 在扩展中包含外部文件,并实现自动更新功能。
Method 1: Fully local copy
方法一:完全本地复制
manifest.json
(only the relevant parts are shown):
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"]
}
]
}
In ga-config.js
, define the variables as follows:
在 中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', '']);
Download https://ssl.google-analytics.com/ga.js, and save it as ga.js
.
Download http://s10.histats.com/js15_as.js, and save it as js15_as.js
.
下载https://ssl.google-analytics.com/ga.js,并将其另存为ga.js
.
下载http://s10.histats.com/js15_as.js,并将其另存为js15_as.js
.
Method 2: Injecting a Up-to-date GA
方法 2:注入最新的 GA
If you want to have an up-to-date version of GA, a convoluted way of injecting the code has to be used, because Content scripts cannot be included from an external URL.
如果您想拥有最新版本的 GA,则必须使用一种复杂的代码注入方式,因为无法从外部 URL 包含内容脚本。
An old version of this answer relied on the background page and chrome.tabs.executeScript
for this purpose, but since Chrome 20, a better method has become available: Use the chrome.storage
API to cache the JavaScript code.
To keep the code updated, I will store a "last updated" timestamp in the storage; you can also use the chrome.alarms
API instead.
此答案的旧版本依赖于背景页面,chrome.tabs.executeScript
为此目的,但自 Chrome 20 以来,已提供更好的方法:使用chrome.storage
API 来缓存 JavaScript 代码。为了保持代码更新,我将在存储中存储一个“上次更新”时间戳;您也可以改用chrome.alarms
API。
Note: Do not forget to include a local copy of the external file in your extension, in case the user does not have an internet connection, etc.Without an internet connection, Google Analytics wouldn't work anyway.
注意:不要忘记在您的扩展程序中包含外部文件的本地副本,以防用户没有互联网连接等。如果没有互联网连接,谷歌分析将无法正常工作。
Content script, activate-ga.js
.
内容脚本,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();
}
Minimum manifest file:
最小清单文件:
{
"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"]
}
The same method can be used for other trackers. The minimum permission requirements:
相同的方法可用于其他跟踪器。最低权限要求:
https://ssl.google-analytics.com/ga.js
, so that should be added at the permissions section.https://*/*
or<all_urls>
is also sufficient.- optional:
unlimitedStorage
- If you want to store a large piece of data withchrome.storage
.
https://ssl.google-analytics.com/ga.js
,所以应该在权限部分添加。https://*/*
或者<all_urls>
也足够了。- 可选:
unlimitedStorage
- 如果你想用chrome.storage
.
回答by gblazex
2015 Update
2015年更新
The new Universal Analyticssnippet can definitely handle multiple trackers, so assuming you give yours a unique name and run allAnalytics code in the page's context, you should be good to go.
新的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);
}
Note, there's one slight modification in the analytics snippet to use document.documentElement
instead of the first <script>
element. It is because google assumes you add analytics in an inline script block, whereas here you add it from a content script.
请注意,要使用的分析片段中有一个轻微的修改,document.documentElement
而不是第一个<script>
元素。这是因为 google 假设您在内联脚本块中添加分析,而在这里您从内容脚本中添加它。
回答by awongh
I read through this thread: https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/yc-ouDqfMw0and found that there's an official chrome method for adding the analytics script to the page, and it's not in the official docs.
我通读了这个线程:https: //groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/ yc-ouDqfMw0并发现有一种官方的 chrome 方法可以将分析脚本添加到页面,它不在官方文档中。
you can refer to this extension for reference: https://github.com/GoogleChrome/chrome-app-samples/tree/master/samples/analyticsand it uses this lib: https://github.com/GoogleChrome/chrome-platform-analytics
您可以参考此扩展程序以供参考:https: //github.com/GoogleChrome/chrome-app-samples/tree/master/samples/analytics它使用此库:https: //github.com/GoogleChrome/chrome-平台分析
basically you manually include the script locally:
基本上你手动在本地包含脚本:
<script src="your_path/google-analytics-bundle.js"></script>
<script src="main.js"></script>
then you call some library functions:
然后调用一些库函数:
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);
};
}
note: apparently, you haveto have an opt out function https://github.com/GoogleChrome/chrome-platform-analytics/wiki#add-privacy-support-aka-opt-out
注意:显然,你必须有一个选择退出功能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;