对document.referrer的理解

1.document.referrer

​ 最近有个需求需要实现一个功能,需要判断用户是从A页面扫码进来的B页面,还是直接在地址栏中输入B页面的的链接进来。当时第一个想到的就是document.referrer。

​ javascript 有一个可以获取前一页面的URL地址的方法:document.referrer

document.referrer 的来源

  1. referrer 属性可返回载入当前文档的文档的 URL, 如果当前文档不是通过超链接访问的,那么当前文档的URL为NULL,这个属性允许客户端的 javascript 访问 HTTP 头部;
  2. referrer 属性,我们可以从 http 头部获取

document.referrer 的兼容性

document.referrer IE7都支持,它的兼容性比较高,Android 5.0开始支持,iOS都支持,PC端浏览器从IE7就开始支持了,兼容性没有什么大的问题。

2、使用场景

​ 从使用意义上来说document.referrer希望能够追踪到的是浏览器端行为。如果B页面被打开,那么浏览器端可能会发生的动作有用户操作、JS代码两种。

先来看看用户打开页面A可能会进行的操作:这里的link即指标签

1 直接在地址栏中输入A的地址
2 从A页面左击link B,跳转至A页面
3 从A页面左击link B,在新窗口中打开
4 从A页面左击link B,在新标签页中打开
5 拖动link A至地址栏
6 拖动link A至标签栏
7 使用浏览器的前进、后退按钮

JS打开页面可能的方式:

1 修改window.location
2 使用window.open

上面列出了客户端打开页面的一些方法,此外,如果通过服务端的重定向技术,也能够使得页面A呈现给访客。

下面来针对具体的浏览器测试,如果是上述的这些情况,document.referrer表现如何:

序号 场景 IE8.0 FF3.6 FF4.0 chrome
1 直接在地址栏中输入B的地址 “ “ “ “ “ “ “ “
2 从A页面左击link B,B页面替换A页面(target=’_self’)
3 从A页面左击link B,B在新窗口中打开(target=’_blank’)
3 从A页面右击link B,在新窗口中打开 “ “
4 从A页面右击link B,在新标签页中打开 “ “
5 鼠标拖动link B至地址栏 “ “ “ “ “ “
6 鼠标拖动link B至标签栏 “ “ “ “ “ “ “ “
7 使用浏览器的前进、后退按钮 保持 保持 保持 保持
8 修改window.location打开B页面(同域) “ “
9 使用window.open打开B页面 “ “
10 服务器重定向至B页面 “ “ “ “ “ “ “ “

其中,” “表示一个空的字符串,√表示能够正确判断来源页,保持则意味使用前进后退不会改变页面的referrer。从这张表里可以看出document.referrer能覆盖大约一半的case。但是对于一些比较常用的操作,例如利用鼠标拖动link至标签栏、前进后退等情况还不能做出正确的处理。

3,无法获取 referrer 信息的情况

下面的场景无法获得 referrer 信息:

  1. 直接在浏览器中输入地址

  2. 使用location.reload()刷新(location.href或者location.replace()刷新有信息)

  3. 在微信对话框中,点击进入微信自身浏览器

  4. 扫码进入微信或QQ的浏览器

  5. 直接新窗口打开一个页面

  6. 从https的网站直接进入一个http协议的网站(Chrome下亲测)

  7. a标签设置rel="noreferrer"(兼容IE7+)

  8. meta标签来控制不让浏览器发送referer

    <meta content="never" name="referrer">
    
  9. 点击 flash 内部链接

  10. Chrome4.0以下,IE 5.5+以下返回空的字符串

  11. 使用 修改 Location 进行页面导航的方法,会导致在IE下丢失 referrer,这可能是IE的一个BUG

  12. 跨域

4.结束语

​ 因为最终的使用场景中,从A页面扫码进入B页面的过程中,后端小哥哥做了302重定向跳转到B页面,这时候在B页面获取到的document.referrer也是""