Chrome扩展将外部javascript添加到当前页面';s html

Chrome扩展将外部javascript添加到当前页面';s html,javascript,dom,google-chrome-extension,google-analytics,content-script,Javascript,Dom,Google Chrome Extension,Google Analytics,Content Script,我正在通过我的chrome扩展向页面末尾添加一些外部JavaScript。然后,外部JavaScript尝试将一些数据发回服务器,但这并没有发生 JavaScript希望获取当前页面和引用者的url,并将其发布回服务器 有谁能告诉我这里出了什么问题,如果不可能,我该如何将当前页面中的数据发布回服务器 manifest.json { "name": "Website Safety", "version": "1.0", "manifest_version": 2, "descrip

我正在通过我的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"]
    }
  ]
}

内容脚本不会在页面()的范围内运行,而是在扩展和网页之间的上下文中运行

因为跟踪器是“注入脚本”类型,所以它们完全在网页的上下文中运行。但是
\u gaq
Hasync
变量没有。因此,跟踪脚本无法读取配置变量

有两(三)种解决方法

  • 使用注入您的代码(如问题中所述)。不鼓励将此方法用于您的目的,因为您的脚本会覆盖常用的全局变量。使用此方法执行脚本将中断许多网站上的跟踪-不要使用它
  • 在内容脚本的范围内完全运行代码:
    两种选择:
  • 在扩展名中包含外部文件
  • 在扩展名中包含外部文件,并实现自动更新功能
  • 方法1:完全本地复制
    manifest.json
    (仅显示相关部分):

    下载并将其另存为
    ga.js

    下载并将其另存为js15_as.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();
    }
    
    方法2:注入最新的GA 如果您想拥有最新版本的GA,必须使用复杂的代码注入方式,因为无法从外部URL包含内容脚本

    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();
    }
    
    这个答案的一个旧版本依赖于后台页面,并且出于这个目的,但是自从Chrome 20以来,一个更好的方法变得可用:使用API缓存JavaScript代码。 为了保持代码的更新,我将在存储器中存储一个“上次更新”的时间戳;您也可以改用API

    注意:不要忘记在扩展名中包含外部文件的本地副本,以防用户没有互联网连接等。如果没有互联网连接,谷歌分析将无法工作

    内容脚本,
    激活-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"]
    }
    
    {
    “名称”:“网站安全”,
    “版本”:“1.0”,
    “清单版本”:2,
    “权限”:[
    “选项卡”、“http://*/*”、“https://*/*”
    ],
    “内容脚本”:[
    {
    “匹配项”:[“”],
    “js”:[“activate-ga.js”]
    }
    ],
    “网络可访问资源”:[“ga.js”]
    }
    
    同样的方法也可用于其他跟踪器。最低许可要求:

    • https://ssl.google-analytics.com/ga.js
      ,因此应将其添加到权限部分<代码>https://*/*或
      也足够了
    • 可选:
      unlimitedStorage
      -如果要使用
      chrome.storage
      存储大量数据

    我通读了这篇文章:发现有一种官方的chrome方法可以将分析脚本添加到页面中,但它不在官方文档中

    您可以引用此扩展以供参考:它使用以下库:

    基本上,您可以在本地手动包含脚本:

      <script src="your_path/google-analytics-bundle.js"></script>
      <script src="main.js"></script>
    
    注意:显然,你必须有一个选择退出功能


    2015年更新

    新的Universal Analytics snippet完全可以处理,因此假设您给自己的代码起了一个唯一的名称并运行all分析代码,那么您就可以开始了

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

    一些代码会很好。您想获取当前页面的URL及其引用,并将特定于用户的私有数据发送到任意服务器?!不是随机服务器,是从同一台服务器获取js的服务器。通过激活此扩展,用户应该能够看到其他人在离开时所做的事情。有一种新的处理方法。请看我的回答:很抱歉,我不得不对此投反对票,因为建议的方法将他锁定在ga.js的静态版本中。它阻止他获得更新,因此应该由谷歌提供。请参阅官方推荐:@galambalazs更新了我的答案,加入了该功能。您好,这听起来很棒,但我面临的问题是,它仍然没有跟踪用户正在浏览的页面。它无法将任何数据发回谷歌的服务器。你能帮我想想我做错了什么吗。我使用了你给我的密码。顺便说一句,谢谢你帮我复习关于这个话题的知识,尽管从谷歌的文档中看起来很容易理解,但我并不是真的这么认为的。我正在对此进行投票,我将尝试几次来修复我可能出现的错误。让它工作起来,但奇怪的是,谷歌分析没有跟踪用户访问了哪些网站以及其他有关用户在网络上的位置的数据。另外,是否有方法知道用户何时打开/关闭选项卡或窗口?@user658911将事件侦听器绑定到。关于跟踪:我的演示效果很好。您是否有其他后台脚本将事件侦听器绑定到
    chrome.extension.onRequest
    ?这是我找到的最佳答案。真是太棒了
    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);
      };
    }
    
    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;
    
    // 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);
    }