如何确定 document.referrer 是否来自自己的网站?

18

每次请求页面时,我会获取该页面来自哪个网站的引荐者。我需要跟踪其他网站的引荐者,而不是跟踪在我的网站内从一个页面到另一个页面的引荐。我该如何做呢?


4
哇,你提出了问题,然后在不到1分钟的时间内回答并附上了指向自己网站的链接? - Martin
2
我想发表解决方案是件好事。我很确定其他人也遇到了同样的问题。 - David Thielen
3
@Richard,实际上 StackOverflow 建议以这种方式发布有用的问答。一旦您获得足够的积分,就可以在单个提交中完成。 - David Thielen
3
是的,这也是 StackOverflow 设立的最初原因之一,让程序员可以粘贴像这样的问答,而不必写博客文章。 - Jeff Davis
实际上,在 SO 中推荐编写自己的问题和答案。但不要只提供外部链接,这并不被认为是一个好答案。 - Константин Ван
5个回答

43
document.referrer.indexOf(location.protocol + "//" + location.host) === 0;

@Eric:不是正则表达式,而是字符串。"//"不需要转义。 - Eli Grey
它不会计算子域引荐。我们有 bags.website.com 和 furniture.website.com,即使用户在同一平台/主域上,这也是错误的。 - Awais Kazi

1

最初发布于JavaScript - 我是引荐者吗?

当有人第一次访问我们的网站时,我们会将引荐者存储在 cookie 中。这样,如果他们下载我们的演示文稿,我们可以从 cookie 中获取原始引荐者,并了解哪些网站对我们的潜在客户产生了推动作用。

当然,访问者在我们网站上点击的每个后续页面都会显示引荐者为我们的网站。我们不想要这些。我们首先采取的方法是查找引荐者中的“windward”文本,如果是,则假定它来自我们的网站。但问题是,我们发现很多引荐者 URL 现在都包含 windward,无论是作为搜索词还是作为谈论 Windward 的 URL 的一部分。(这是好消息,这意味着我们现在是一个知名产品。)

因此,这就带我到了我们最近的方法。这应该适用于任何网站,并且只应拒绝来自同一网站的引荐者。

function IsReferredFromMe()
{

    var ref = document.referrer;
    if ((ref == null) || (ref.length == 0)) {
        return false;
    }
    if (ref.indexOf("http://") == 0) {
        ref = ref.substring(7);
    }
    ref = ref.toLowerCase();

    var myDomain = document.domain;
    if ((myDomain == null) || (myDomain.length == 0)) {
        return false;
    }
    if (myDomain.indexOf("http://") == 0) {
        myDomain = myDomain.substring(7);
    }
    myDomain = myDomain.toLowerCase();

    return ref.indexOf(myDomain) == 0;
}

那不会破坏 https 吗? - AncientSwordRage
@Pureferret - 是的,也需要处理https。这是在2010年编写的,当时公共网站几乎都是http。 - David Thielen

0
如果你认为“同一网站”的页面具有相同的起源(相同的协议主机端口),

URL syntax diagram

用这种方式进行检查:

function the_referrer_has_the_same_origin() {
    try {
        const referrer = new URL(document.referrer);
        return (referrer.origin === location.origin);
    } catch(invalid_url_error) {
        return false;
    }
}
// Works as intended for `https://www.google.com` and `https://www.google.com:443`.

.

如果您想要一个简短的答案而不考虑不太可能的情况,可以尝试这个:
document.referrer.startsWith(location.origin)
// Fails for `https://www.google.com` and `https://www.google.com:443`.

.


0

如果网站中没有子域名,则所提供的解决方案有效;如果存在子域名,则我们必须在域名之前检查是否存在任何子域名。

document.referrer.replace("http://", '').replace("https://", '').split('/')[0].match(new   RegExp(".*" +location.host.replace("www.", '')))

这个解决方案将在域名前添加.*以检测子域是否来自同一域名。


-2
document.referrer.includes(location.host);

不错的解决方案,但请注意IE不支持includes()方法(https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) - wk_
1
这不安全。你应该只从字符串的开头开始测试,因为引用者可能将你的主机作为其子集包含在内:例如,“notactuallygoogle.com”将与你的方法中的“google.com”匹配。 - Eli Grey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接