0%

Next主题集成revolvermaps访问统计功能

Next主题集成revolvermaps访问统计功能。

1. revolvermaps的使用

访问revolvermaps,点击Get a Widget,获取RevolverMaps Button Widget,会生成一段js。

1
<script type="text/javascript" src="//rf.revolvermaps.com/0/0/3.js?i=07plr0asvn58&amp;b=0&amp;s=20&amp;m=2&amp;cl=ffffff&amp;co=010020&amp;cd=aa0000&amp;v0=60&amp;v1=60&amp;r=1" async="async"></script>

其中参数i=07plr0asvn58是我们网站的追踪ID,s=20是大小20px。

2. revolvermaps的api分析

把上面的代码复制到我们网站,看到它请求了一段js:

1
http://rf.revolvermaps.com/0/0/3.js?i=07plr0asvn5&b=0&s=20&m=0&cl=ffffff&co=010020&cd=aa0000&v0=60&v1=60&r=1

这段js的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var _rm5tat30bj_ = _rm5tat30bj_ || {
a: {},
b: []
}; (function(d, o) {
var e, a, s, t = d.getElementsByTagName('script'),
i = t.length;
w: while (i--) {
e = t[i];
if (e.src) {
a = d.createElement('a');
a.href = (e.src.match(/^\/\//) ? 'http:': '') + e.src;
if (a.hostname.match(/\.revolvermaps\.com$/i) && a.pathname.match(/^\/?0\/0\/3\.js$/)) {
s = o.b.length;
while (s--) if (o.b[s] === e) continue w;
o.b.push(e);
function p(t) {
t = new RegExp('[&\\?]' + t + '=([^&]*)').exec(a.search);
return t ? t[1] : '';
}
function b(i, w, h) {
i = d.createElement('iframe');
i.setAttribute('style', 'background:transparent !important');
i.setAttribute('scrolling', 'no');
i.setAttribute('frameborder', '0');
i.setAttribute('allowTransparency', 'true');
h = p('b');
if ( + h) {
w = [, 103, 88, 97, 100, 99, 103, 88, 97, 100, 99][h];
h = [, 18, 34, 34, 34, 18, 18, 34, 34, 34, 18][h];
} else w = h = p('s');
if ( + w) {
i.setAttribute('width', w);
i.setAttribute('height', h);
i.setAttribute('src', '//' + a.hostname + '/w/3/j/a/' + (window.ArrayBuffer ? 'c2': 'b') + '.php' + a.search);
e.parentNode.insertBefore(i, e);
}
}
s = p('i');
if (!o.a[s]) {
o.a[s] = [b];
i = new Image;
i.onload = i.onerror = function() {
while (o.a[s].length) o.a[s].pop()();
o.a[s] = 1;
};
i.src = '//' + a.hostname + '/js/c.php?i=' + s;
t = new Image;
t.onload = function() {
this.width = 1;
};
t.src = '//' + a.hostname + '/js/r.php?i=' + s + '&l=' + encodeURIComponent(d.URL) + '&r=' + new Date().getTime();
} else if (o.a[s] === 1) b();
else {
o.a[s].push(b);
}
break;
}
}
}
})(document, _rm5tat30bj_);

这个js又请求了下面三个网址。

第一个网址:

1
http://rf.revolvermaps.com/w/3/j/a/c2.php?i=07plr0asvn5&b=0&s=20&m=0&cl=ffffff&co=010020&cd=aa0000&v0=60&v1=60&r=

它返回了一个网页,使用canvas生成了3d地球,同时它又请求了 http://rf.revolvermaps.com/w/3/j/b/a.php ,返回了_X=0.24305;_Y=0.26244;估计是访问者在3d地球上的坐标。

第二个网址:

1
https://rf.revolvermaps.com/js/r.php?i=07plr0asvn5&l=https%3A%2F%2Fblog.maplesugar.top%2F&r=1584587155905

它返回了一个尺寸为1x1的图像,实际上是把访问者的信息上传给revolvermaps。
l参数上传网址,r参数是new Date().getTime()。

第三个网址:

1
http://rf.revolvermaps.com/js/c.php?i=07plr0asvn5

它也返回了一个尺寸为1x1的图像,一开始我不知道有什么用,后来才发现这是页面计数。我以为了第二个网址就有计数功能。

3. 显示3d地球

把返回网页的地址http://rf.revolvermaps.com/w/3/j/a/c2.php?i=07plr0asvn5&b=0&s=20&m=0&cl=ffffff&co=010020&cd=aa0000&v0=60&v1=60&r=复制到iframe中就好了。

/themes/next/layout/_partials/footer.swig
1
2
3
4
5
6
7
8
9
10
<div class="copyright">最后插入

{# revolvermaps访问统计 #}
<span class="post-meta-divider">|</span>
<span id="revolvermaps_3dmap" class="post-meta-item-icon">
<a id="revolvermaps_icon" class="fa fa-globe" style="border-bottom:none;text-decoration:none;" href="https://www.revolvermaps.com/?target=enlarge&i=07plr0asvn5" title="click to open the RevolverMaps live statistics"></a>
<iframe id="revolvermaps_iframe" style="background:transparent !important;display:none;" scrolling="no" frameborder="0" allowtransparency="true" width="20" height="20" src="//rf.revolvermaps.com/w/3/j/a/c2.php?i=07plr0asvn5&amp;b=0&amp;s=20&amp;m=0&amp;cl=ffffff&amp;co=010020&amp;cd=aa0000&amp;v0=60&amp;v1=60&amp;r=1"></iframe>
<!-- <script type="text/javascript" src="//rf.revolvermaps.com/0/0/3.js?i=07plr0asvn5&amp;b=0&amp;s=20&amp;m=0&amp;cl=ffffff&amp;co=010020&amp;cd=aa0000&amp;v0=60&amp;v1=60&amp;r=1" async="async"></script> -->
</span>
<span id="revolvermaps_visits_count" title="访问次数">loading</span>

在\themes\next\layout_partials\analytics添加也行,就是跑到下一行去了。

revolvermaps_icon的作用是,在iframe没有加载完成的时候,仍然显示一个globe图标。

Pjax开启后,在body-end.swig中自定义的js,在Pjax刷新页面的时候,仍然能够重新加载。

/source/_data/body-end.swig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!-- revolvermaps_iframe加载成功后,隐藏fontasome globe icon -->
<script>
var revolvermaps_iframe = document.getElementById('revolvermaps_iframe');
//ie浏览器
if (revolvermaps_iframe.attachEvent) {
revolvermaps_iframe.attachEvent("onreadystatechange",
function() {
//此事件在内容没有被载入时候也会被触发,所以我们要判断状态
//有时候会比较怪异 readyState状态会跳过 complete 所以我们loaded状态也要判断
if (revolvermaps_iframe.readyState === "complete" || iframe.readyState == "loaded") {
//代码能执行到这里说明已经载入成功完毕了
//console.log("iframe加载完毕");
document.getElementById('revolvermaps_icon').style.display="none";
this.style.display="inline-block";
//要清除掉事件
revolvermaps_iframe.detachEvent("onreadystatechange", arguments.callee);
//这里是回调函数
}
});
//其他浏览器(Firefox,Opera,chrome等 )
} else {
revolvermaps_iframe.addEventListener("load",
function() {
//代码能执行到这里说明已经载入成功完毕了
//console.log("iframe加载完毕");
document.getElementById('revolvermaps_icon').style.display="none";
this.style.display="inline-block";
this.removeEventListener("load", arguments.call, false);
//这里是回调函数
},
false);
}
</script>

这是iframe的样式。

1
2
3
4
5
6
/* revolvermaps 3d图标 */
#revolvermaps_3dmap iframe {
display: inline-block;
//因为我们的3d地球图标是20px,copyright div computed的高度是28px
margin-bottom: -4px;
}

设置Pjax每次刷新页面,都重新加载id为revolvermaps_3dmap的<span>,也就重新加载了3d地球的iframe。

/themes/next/layout/_scripts/pjax.swig
1
2
3
4
5
6
7
8
selectors: [
'head title',
'#page-configurations',
'.content-wrap',
'.post-toc-wrap',
'#pjax',
'#revolvermaps_3dmap'
]

4. 访问统计

/source/_data/body-end.swig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 上传revolvermaps统计 -->
<script type="text/javascript">
if (location.href.indexOf("localhost") > -1 || location.href.indexOf("127.0.0.1") > -1) {
    console.log("本地浏览,不上传统计");
    } else {
var revolvermaps_img = new Image;
revolvermaps_img.onload = function() {
this.width = 0;
};
revolvermaps_img.src = 'https://rf.revolvermaps.com/js/r.php?i=07plr0asvn5' + '&l=' + encodeURIComponent(document.URL) + '&r=' + new Date().getTime();
var revolvermaps_count_img = new Image;
revolvermaps_count_img.onload = function() {
this.width = 0;
};
revolvermaps_count_img.src = 'https://rf.revolvermaps.com/js/c.php?i=07plr0asvn5' + '&r=' + new Date().getTime();
}
</script>

这里用到了上面的计数api:http://rf.revolvermaps.com/js/c.php?i=07plr0asvn5,上传访问者位置api:https://rf.revolvermaps.com/js/r.php?i=07plr0asvn5&l=https%3A%2F%2Fblog.maplesugar.top%2F&r=1584587155905

5. 显示计数

查看https://www.revolvermaps.com/livestats/07plr0asvn5页面,发现它的计数是通过https://rf.revolvermaps.com/i/r3.php?i=07plr0asvn5 获取的。

https://rf.revolvermaps.com/i/r3.php?i=07plr0asvn5 返回的内容

1
1<1547121966<4200<1<1<us<1<1<us>Clifton, New Jersey>1584590526>0>00:02:06>EDT>America/New_York>-04:00>

第三个数字就是访问计数。

直接通过ajax访问,会因为跨域报错。

Access to XMLHttpRequest at ‘https://rf.revolvermaps.com/i/r3.php?i=07plr0asvn5' from origin ‘http://localhost:4000' has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

尝试使用netlify代理网址解决跨域,netlify能添加header。理论上添加上Access-Control-Allow-Origin就可以了。但实际尝试不可以,netlify不可以在redirects requests的返回中注入header。

1
2
3
4
5
6
7
8
9
10
11
12
13
[[redirects]]
from = "/blog-maplesugar-revolvermaps-visits-count/"
to = "https://rf.revolvermaps.com/i/r3.php?i=07plr0asvn5"
status = 200
force = true
[redirects.headers]
Cache-Control = "no-cache"
User-Agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
[[headers]]
# Define which paths this specific [[headers]] block will cover.
for = "/*"
[headers.values]
Access-Control-Allow-Origin = "*"

使用nginx注入Access-Control-Allow-Origin的header。

1
2
3
4
5
6
7
8
9
10
11
12
13
server {
listen 80;
server_name proxy.maplesugar.top;
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Cache-Control' 'no-cache';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';

# 代理服务端接口
location /blog-maplesugar-revolvermaps-visits-count {
proxy_pass https://rf.revolvermaps.com/i/r3.php?i=07plr0asvn5; #将真正的请求代理到API 服务地址
}
}

这样访问http://proxy.maplesugar.top/blog-maplesugar-revolvermaps-visits-count就没有跨域的报错了,再使用netlify代理,避免了重签https证书的烦恼。

/source/_data/body-end.swig
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 请求revolvermaps访问量 -->
<script>
$.ajax({
type: "GET",
async: true,
url: "https://jolly-goodall-4ade03.netlify.com/blog-maplesugar-revolvermaps-visits-count",
success: function (data) {
//console.log(data);
$("#revolvermaps_visits_count").text(data.split('<')[2]);
}
});
</script>

6. 其他同类工具

ClustrMaps