【问题标题】:Why serve 1x1 pixel GIF (web bugs) data at all?为什么要提供 1x1 像素的 GIF(网络错误)数据?
【发布时间】:2019-08-13 23:18:40
【问题描述】:

许多分析和跟踪工具都要求 1x1 GIF 图像(网络错误,用户不可见)用于跨域事件存储/处理。

为什么要提供这个 GIF 图像? 简单地返回一些错误代码,例如 503 Service Temporary Unavailable 不是更有效率 em> 还是空文件?

更新:为了更清楚,我问为什么在请求标头中已发送所有所需信息时提供 GIF 图像数据。 GIF 图像本身不返回任何有用的信息。

【问题讨论】:

    标签: javascript html google-analytics


    【解决方案1】:

    Doug 的回答非常全面;我想我会添加一个额外的注释(应 OP 的要求,我的评论)

    Doug 的回答解释了为什么 1x1 像素信标用于其用途;我想我会概述一种潜在的替代方法,即使用 HTTP 状态代码 204,无内容作为响应,而不是发送图像正文。

    204 无内容

    服务器已完成请求 但不需要返回 实体主体,并且可能想要返回 更新的元信息。响应 可能包括新的或更新的 元信息的形式 实体标头,如果存在 应该与 请求的变体。

    基本上,服务器收到请求,并决定不发送正文(在这种情况下,不发送图像)。但它会回复一个代码来通知代理这是一个有意识的决定;基本上,它只是一种较短的肯定回应方式。

    来自Google's Page Speed documentation

    一种流行的记录页面方式 异步方式的视图是 在 目标页面的底部(或作为 onload 事件处理程序),通知一个 当用户加载日志服务器时 页。最常见的做法 这是构造一个请求 服务器的“信标”,并编码所有 感兴趣的数据作为参数 信标资源的 URL。至 保持 HTTP 响应非常小,a 透明的 1x1 像素图像很好 信标请求的候选人。一个 稍微更优的信标将使用 HTTP 204 响应(“无内容”) 略小于 1x1 GIF。

    我从未尝试过,但理论上它应该可以达到相同的目的,而不需要传输 gif 本身,在 Google Analytics 的情况下为您节省 35 个字节。 (在事物的计划中,除非您是 Google Analytics(分析)每天提供数万亿次点击,否则 35 字节真的不算什么。)

    您可以使用以下代码对其进行测试:

    var i = new Image(); 
    i.src = "http://httpstat.us/204";
    

    【讨论】:

    • 这些鲜为人知的 HTTP 状态代码(203、204、205)真的是黄金。他们应该看到比现在更多的用处。
    • 不错的——事实上,我可以使用的信息。来自我的 +1。
    • 让我看看能不能总结一下——HTTP响应代码方法涉及到same客户端请求;唯一的区别是服务器,而不是返回 1x1 gif(和 200,我想),而是返回 204 给客户端?
    • 你会如何请求返回 204 响应代码的东西?
    • 我不明白为什么图像。为什么不返回一个空字符串?
    【解决方案2】:

    首先,我不同意前面的两个答案——都没有涉及到这个问题。

    单像素图像解决了在 HTTP 协议中工作时基于网络的分析应用程序(如 Google Analytics)的一个内在问题——如何将(网络指标)数据从客户端传输到服务器

    协议描述的最简单的方法,最简单的(至少是包含请求主体的最简单的方法)是GET 请求。根据该协议方式,客户端向服务器发起资源请求;服务器处理这些请求并返回适当的响应。

    对于像 GA 这样的基于 Web 的分析应用程序,这种单向方案是个坏消息,因为它似乎不允许服务器按需从客户端检索数据——同样,所有服务器都可以做的是提供资源而不是请求它们。

    那么解决将数据从客户端返回到服务器的问题的解决方案是什么? 在 HTTP 上下文中,除了 GET(例如 POST)之外,还有其他协议方法,但这是一个有限的选择出于多种原因(如提交表单数据等不常见且专门的用途证明)。

    如果您从浏览器查看 GET 请求,您会发现它由请求 URL 和 请求标头(例如,Referer 和 User-Agent Headers),后者包含有关客户端的信息——例如,浏览器类型和版本、浏览器语言、操作系统等。

    同样,这是客户端发送到服务器的请求的一部分。所以激发单像素 gif 的想法是让客户端将 Web 指标数据发送到服务器,并封装在请求标头中。

    然后如何让客户端请求资源,以便它可以被“欺骗”发送指标数据?以及如何让客户端发送服务器想要的实际数据?

    Google Analytics 就是一个很好的例子:ga.js 文件(由网页中的小脚本触发下载到客户端的大文件)包含几行代码,指示客户端从特定服务器(GA 服务器)请求特定资源,并发送包装在请求标头中的特定数据。

    但是由于这个 Request 的目的不是实际获取资源,而是向服务器发送数据,所以这个资源应该尽可能小,并且在呈现在网页中时不应该是可见的——因此, 1 x 1 像素透明 gif。尺寸是可能的最小尺寸,格式 (gif) 是图像格式中最小的。

    更准确地说,所有 GA 数据(每一项)都被组装并打包到 请求 URL 的查询字符串(“?”之后的所有内容)中。但是为了让数据从客户端(创建它的地方)到 GA 服务器(记录和聚合它的地方),必须有一个 HTTP 请求,所以 ga.js(下载的谷歌分析脚本,除非它是由客户端缓存,作为页面加载时调用的函数的结果)指示客户端组装所有分析数据 - 例如,cookie、位置栏、请求标头等 - 将其连接成单个字符串并将其作为查询字符串附加到 URL (*http://www.google-analytics.com/__utm.gif*?) 并成为 请求 URL .

    使用任何允许您查看浏览器中显示的网页的 HTTP 请求的网络浏览器很容易证明这一点(例如,Safari 的 Web Inspector、Firefox/Chrome Firebug 等)。

    例如,我在浏览器的位置栏中输入了公司主页的有效 url,它返回该主页并将其显示在我的浏览器中(我可以选择使用主要分析之一的任何网站/页面应用程序、GA、Omniture、Coremetrics 等)

    我使用的浏览器是 Safari,所以我点击了菜单栏中的 Develop,然后点击了 Show Web Inspector。在 Web Inspector 的第一行,单击 Resources,从左侧列中显示的资源列表中找到并单击 utm.gif 资源,然后单击 Headers 选项卡。这将向您显示如下内容:

    Request URL:http://www.google-analytics.com/__utm.gif?
               utmwv=1&utmn=1520570865&
               utmcs=UTF-8&
               utmsr=1280x800&
               utmsc=24-bit&
               utmul=enus&
               utmje=1&
               utmfl=10.3%20r181&
    
    Request Method:GET
    Status Code:200 OK
    
    Request Headers
        User-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/533.21.1 
                     (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
    
    Response Headers
        Cache-Control:private, no-cache, no-cache=Set-Cookie, proxy-revalidate
        Content-Length:35
        Content-Type:image/gif
        Date:Wed, 06 Jul 2011 21:31:28 GMT
    

    需要注意的关键点是:

    1. 请求实际上是一个请求 对于 utm.gif,由 上面的第一行:*请求 网址:http://www.google-analytics.com/__utm.gif*。

    2. Google Analytics 参数在查询字符串中清晰可见 附加到请求 URL:例如, utmsr 是 GA 的变量名,用于引用客户端屏幕 对我来说,分辨率显示的值为 1280x800; utmfl 是变量 flash 版本的名称,它有一个 值 10.3 等。

    3. 响应头调用 Content-Type(由服务器发送回客户端)也确认 请求的资源和 返回的是一个 1x1 像素的 gif: 内容类型:图像/gif

    这种在客户端和服务器之间传输数据的通用方案一直存在;很可能有更好的方法来做到这一点,但这是我所知道的唯一方法(满足托管分析服务施加的限制)。

    【讨论】:

    • @doug 很棒的答案。我希望我已经写了它 :) 可能值得一提的是可能能够使用HTTP Status Code 204 进行回复。看到这个:code.google.com/speed/page-speed/docs/rtt.html我从来没有尝试过,但理论上它应该服务于相同的目的,而不需要传输 gif 本身。 var i=new Image(); i.src = "http://sharedcount.com/test/beacon.gif"; 是一个例子,但我不确定它是否会出现任何浏览器问题。
    • 这不是最糟糕的答案,因为它不是答案 :) 我问为什么要提供 GIF 图片,因为所需的数据已经随请求一起发送了。
    • 我不想太消极,抱歉。这是对网络错误的很好解释。但是为什么要返回 GIF 数据呢?
    • @yahelc:太好了。考虑将其添加为其他人的答案。作为评论,它几乎是不可见的。
    • @Villiam 当然,刚刚添加。
    【解决方案3】:

    如果资源无法加载,某些浏览器可能会显示错误图标。它使调试/监控服务也有点复杂,您必须确保您的监控工具将错误视为一个好的结果。

    OTOH,你什么也得不到。服务器/框架返回的错误消息通常比 1x1 图像大。这意味着您基本上不会增加​​网络流量。

    【讨论】:

    • 分析应用程序(例如,Google Analytics、Yahoo Analytics、Omniture 等)在网页上放置 1x1 像素 gif 图像的原因绝对没有可做通过“调试”应用程序。
    • @doug - 我认为 mru 的意思是,如果您故意返回错误代码,那么您必须区分“真实”错误代码和您打算返回的错误代码。所以这个故事的寓意是,当结果是预期的结果时,永远不要返回错误代码。
    • 我怀疑错误响应会大于 GIF 图像 - 请注意,200 OK 是响应以及与 GIF 图像一起发送的。
    • @Villiam 大多数环境不仅返回错误代码,而且还返回一个样式精美的 html 页面来描述错误/提供更多信息。
    【解决方案4】:

    因为这样的 GIF 在浏览器中具有已知的呈现方式 - 它是单个像素,句号。其他任何内容都存在在视觉上干扰页面实际内容的风险。

    HTTP 错误可能显示为超大的错误文本框,甚至是弹出窗口。如果收到空回复,某些浏览器也可能会抱怨。

    此外,页内图像是所有浏览器默认允许的极少数数据类型之一。其他任何内容都可能需要下载明确的用户操作。

    【讨论】:

    • 您的回答没有说​​明提供资源的目的——即,为什么需要提供资源?您的答案是针对“为什么提供 1x1 gif 而不是另一种图像格式?这是一个微不足道的问题,答案很简单(即 gif 格式在逐像素的基础上比 jpeg、png 的尺寸更小)” , tiff 等)
    • 您可以使用 Javascript Image 对象调用 GIF 加载。它不会向用户报告任何错误。
    • @Villiam 通过真正返回图像,您还可以跟踪未启用 javascript 的浏览器,只需将图像标签放入 <noscript> 即可。而且您无需在服务器端做任何事情来区分通过 js 的请求(返回错误)和直接通过 DOM 中的元素的请求(返回图像)
    【解决方案5】:

    这是为了回答 OP 的问题——“为什么要提供 GIF 图像数据...”

    有些用户会放一个简单的img标签来调用你的事件日志服务-

    <img src="http://www.example.com/logger?event_id=1234">
    

    在这种情况下,如果您不提供图片,浏览器会显示一个占位符图标,看起来很难看,并给人一种您的服务已损坏的印象!

    我要做的是,寻找 Accept 标头字段。当您的脚本通过这样的 img 标签调用时,您会在请求的标头中看到类似以下内容 -

    Accept: image/gif, image/*
    Accept-Encoding:gzip,deflate
    ...
    

    Accept 标头字段中有 "image/"* 字符串时,我提供图像,否则我只回复 204。

    【讨论】:

      【解决方案6】:

      主要的原因是附加 cookie,所以如果用户从一侧移动到另一侧,我们仍然有相同的元素可以附加 cookie。

      【讨论】:

        【解决方案7】:

        如果您使用 Beacon API (https://w3c.github.io/beacon/) 实现方法,则不必提供图像。

        如果您有权访问服务器的日志文件,则错误代码将起作用。提供图像的目的是获取比通常使用日志文件更多的用户数据。

        【讨论】:

          【解决方案8】:

          @Maciej Perliński 基本上是正确的,但我觉得详细的回答会有所帮助。

          为什么是 1x1 GIF 而不是 204 No-Content 状态码?

          204 No-Content 使服务器可以省略所有响应头(Content-Type、Content-Length、Content-Encoding、Cache-Control 等)并返回一个 0 字节的空响应正文(并节省大量不需要的带宽)。

          浏览器知道尊重204 No-Content 响应,而不是期待/等待响应标头和响应正文。

          如果服务器需要设置任何响应头(例如cache-controlcookie),他不能使用204 No-Content,因为浏览器会有意忽略任何响应头(根据 HTTP 协议规范)。

          为什么是 1x1 GIF 而不是带有 200 OK 状态码的 Content-Length: 0 标头?

          可能是几个问题的混合,仅举几例:

          • 旧版浏览器兼容性
          • 浏览器上的 MIME 类型检查,0 字节不是有效图像。
          • 中间代理服务器和 VPN 可能不完全支持 0 字节的 200 OK

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-01-14
            • 1970-01-01
            • 2013-11-01
            • 1970-01-01
            • 2017-05-07
            • 1970-01-01
            相关资源
            最近更新 更多