Chrome扩展程序将外部JavaScript添加到当前页面的html中
Chrome extension adding external javascript to current page's html
我正在通过我的chrome扩展程序在页面末尾添加一些外部JavaScript。然后,外部 JavaScript 尝试将一些数据发布回服务器,但这并没有发生。
JavaScript 想要获取当前页面和引用者的 url 并将其发布回服务器。
任何人都可以告诉我这里出了什么问题,如果不可能,我该如何才能将数据从当前页面发布回服务器。
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"]
}
]
}
现在内容脚本.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);
})();
内容脚本不在页面范围内运行(另请参阅),它们在扩展和网页之间的上下文中运行。
由于跟踪器的类型是"注入脚本",因此它们完全在网页的上下文中运行。但_gaq
和Hasync
变量则没有。因此,跟踪脚本无法读取配置变量。
有两(三)种方法可以修复它。
- 使用此方法注入您的代码(如问题中所述)。不建议将此方法用于您的目的,因为您的脚本会覆盖常用的全局变量。使用此方法实现脚本将破坏许多网站上的跟踪 - 不要使用它。
- 在内容脚本范围内完全运行代码:
两个选项:- 在扩展名中包含外部文件
- 在扩展中包含外部文件,并实现自动更新功能。
方法 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,则必须使用复杂的代码注入方式,因为无法从外部 URL 包含内容脚本。
这个答案的旧版本依赖于背景页面和chrome.tabs.executeScript
来实现此目的,但从 Chrome 20 开始,一种更好的方法已经可用:使用 chrome.storage
API 缓存 JavaScript 代码。为了保持代码更新,我将在存储中存储"上次更新"时间戳;您也可以改用chrome.alarms
API。
注意:不要忘记在扩展中包含外部文件的本地副本,以防用户没有互联网连接等。
内容脚本, 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
存储大段数据。
2015 更新
新的通用分析代码段绝对可以处理多个跟踪器,因此假设您为自己指定一个唯一的名称并在页面上下文中运行所有分析代码,您应该很高兴。
// 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>
元素。这是因为谷歌假设你在内联脚本块中添加分析,而在这里你从内容脚本中添加它。
我通读了这个线程: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-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;
- 如何在端口80上使用node.js提供单页html
- 获取当前页面的URL并将其附加到Facebook共享链接(使用javascript)
- 如何处理在多页 HTML/jquery 应用程序中链接到脚本和 css 文件
- 基于当前内部HTML创建动态jQuery变量名称
- 如何在 safari 中获取当前页面的 url 和标题
- Javascript无法正常运行?(忽略我当前的 html 值)
- Chrome扩展程序将外部JavaScript添加到当前页面的html中
- 在服务器更改时自动更新/重新加载当前页面的库
- 检测具有 href 属性的“A”标记,该属性等于当前页面的 URL
- 如何定义相对于当前页面的 URL w jQuery
- 具有数据切换操作的分页html
- document.write()覆盖当前的HTML内容.如何绕过这一点
- reveal.js转换为单页html
- 下载当前的html文件
- 我想通过javascript生成当前页面的url,并添加两个参数
- 从当前页面的URL中删除哈希
- 如何在手风琴导航菜单中设置当前页面子链接及其父链接的样式
- Javascript获取当前页面的html
- 解析当前页面的html
- 如何查找当前页面的url(如“index.html”)