# 05 主题集成友链访问统计

前段时间小站添加了不少友链，好奇这些友链的转换价值，偷偷在主题里埋了个小功能来统计这个无人小站的游客访问来源，目前已稳定运行了近半月，统计了下近期友链访问数据。

### document.referrer

这个统计功能主要是使用了[document.referrer](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/referrer)，它返回跳转或打开到当前页面的那个页面的 URI。如果用户直接打开了这个页面（不是通过页面跳转，而是通过地址栏或者书签等打开的），则该属性为空字符串。目前主流桌面浏览器基本都支持这个 API。

![Can I Use](/files/gRlwrFp4bsWMVxFDF5fa)

### 代码实现

接下来先看下半个月所有访问这个无人小站的来源，如果是通过书签或者直接访问的话 document.referrer 为空，访问来源就是本站。好吧，从数据看起来这个站还真无人气，最后感谢下白喵的友链，居然能有辣么多人点进来看\~

![半月访问统计](/files/JlVim8ym4W9WBnOjWpSX)

最后来一份实现代码：

```javascript
// 转换访问来源地址
const getLocation = (href) => {
  const a = document.createElement("a")
  a.href = href
  return a
}

// 统计访客数据
const visitorStatistics = () => {
  const referrer = getLocation(document.referrer)
  const hostname = referrer.hostname

  return new Promise((resolve) => {
    const query = new AV.Query("Visitor")
    const Visitor = AV.Object.extend("Visitor")
    query.equalTo("referrer", hostname)
    query
      .first()
      .then((res) => {
        // 存在则增加访问次数
        if (res) {
          res
            .increment("time", 1)
            .save(null, { fetchWhenSave: true })
            .then(() => resolve())
            .catch(console.error)
        } else {
          // 不存在则新建
          const newVisitor = new Visitor()
          newVisitor.set("referrer", hostname)
          newVisitor.set("time", 1)
          newVisitor
            .save()
            .then(() => resolve())
            .catch(console.error)
        }
      })
      .catch(console.error)
  }).catch(console.error)
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chanshiyu.gitbook.io/blog/shi-yu/2019/05-zhu-ti-ji-cheng-you-lian-fang-wen-tong-ji.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
