Fetch as Google で Google ロボットが使える JavaScript を調べてみる
- カテゴリ:
- Webサービス
- JavaScript
- コメント数:
- Comments: 4
◆ Fetch as Google のクライアントは Chrome 27 のよう
◆ その頃に対応してなかった機能は動かない
◆ そこでエラーになるので JavaScript が全く実行されないときもある
◆ その頃に対応してなかった機能は動かない
◆ そこでエラーになるので JavaScript が全く実行されないときもある
これの続きです
前回は アロー関数が Google の JavaScript 実行環境だと動かなくてその JavaScript のブロックがエラーになってしまって正しく表示されないことがわかりました
ですが const など ES6 で追加された機能で動くものもあります
Fetch as Google を他人のサイトでも使えれば ECMAScript 6 compatibility table などに試してみれば一覧がわかるのですが そうは行かないので 自分が使いそうな機能を適当にいくつか試してみました
こんな HTML を用意しました
Chrome で実行するとエラー無しでこうなります
console 出力じゃないので 文字列化するために JSON.stringify してます
その都合で関数は なくなりますが エラーが出てないなら使えていると判断できます
これを Fetch as Google にかけると

小さくて見づらいのですが Unexpected token となっているものが多いです
まとめると
というところ
まだ試してない機能もいろいろですが 使える基準がよくわかりません
polyfill 可能な関数は使えて 構文はダメ ならわかりやすいのですけど for-of や let はつかえますし Array.from は使えません
navigators のキー一覧は enumerable:false のようで取れないので 今の Chrome にあるものを直接指定しました
まずは Chrome 56 のときの場合
Search Console だと
bot という情報しかわかりません
諦めかけたのですが これまで違いがなかった左右で結果が変わっていました
右側の結果はこうなっていました
Chrome27 !
Google ってセキュリティがどうこういう割には古いの使ってるんですね
あくまで右側の 「あなたのサイトはこう見えてます」 の方で 「Googlebot はこう認識しました」 の方ではありません
ただ ES6 の対応具合などいくつかのパターンを試してみても navigator 以外は全く一緒の結果なので Chrome 27 と考えて大丈夫かと思います
前回は アロー関数が Google の JavaScript 実行環境だと動かなくてその JavaScript のブロックがエラーになってしまって正しく表示されないことがわかりました
ですが const など ES6 で追加された機能で動くものもあります
Fetch as Google を他人のサイトでも使えれば ECMAScript 6 compatibility table などに試してみれば一覧がわかるのですが そうは行かないので 自分が使いそうな機能を適当にいくつか試してみました
こんな HTML を用意しました
<!doctype html>
<meta charset="utf-8">
<div></div>
<script>
function add(title, contents){
var h1 = document.createElement("h1")
h1.innerHTML = title
var div = document.createElement("div")
div.innerHTML = JSON.stringify(contents, null, " ")
var hr = document.createElement("hr")
document.body.appendChild(h1)
document.body.appendChild(div)
document.body.appendChild(hr)
}
function tryAndPrint(title, text){
try{
add(title, eval(text))
}catch(e){
add(title, "Error\n" + e.message + "\nstack" + e.stack + "\n")
}
}
tryAndPrint("Map.toString", "Map.toString()")
tryAndPrint("Set.toString", "Set.toString()")
tryAndPrint("fetch.toString", "fetch.toString()")
tryAndPrint("Array.from.toString", "Array.from.toString()")
tryAndPrint("Promise.toString", "Promise.toString()")
tryAndPrint("let", "const l = 1")
tryAndPrint("const", "const c = 1")
tryAndPrint("typeof symbol", "typeof Symbol()")
tryAndPrint("arrow function", "(e => 1)")
tryAndPrint("template", "String.raw `a\nb`")
tryAndPrint("generator", "(function* gen(){})")
tryAndPrint("expo operator", "3 ** 4")
tryAndPrint("for of", "for(var i of [99]) i")
tryAndPrint("async function", "(async function f(){})")
tryAndPrint("default param", "(function(a = 1){})")
tryAndPrint("... operator", "[...[1]]")
tryAndPrint("method definition", "({method(){}})")
tryAndPrint("object initializer", "var oi = 100;({oi})")
tryAndPrint("object key expression", "({['a' + 'b']: 1})")
</script>
<meta charset="utf-8">
<div></div>
<script>
function add(title, contents){
var h1 = document.createElement("h1")
h1.innerHTML = title
var div = document.createElement("div")
div.innerHTML = JSON.stringify(contents, null, " ")
var hr = document.createElement("hr")
document.body.appendChild(h1)
document.body.appendChild(div)
document.body.appendChild(hr)
}
function tryAndPrint(title, text){
try{
add(title, eval(text))
}catch(e){
add(title, "Error\n" + e.message + "\nstack" + e.stack + "\n")
}
}
tryAndPrint("Map.toString", "Map.toString()")
tryAndPrint("Set.toString", "Set.toString()")
tryAndPrint("fetch.toString", "fetch.toString()")
tryAndPrint("Array.from.toString", "Array.from.toString()")
tryAndPrint("Promise.toString", "Promise.toString()")
tryAndPrint("let", "const l = 1")
tryAndPrint("const", "const c = 1")
tryAndPrint("typeof symbol", "typeof Symbol()")
tryAndPrint("arrow function", "(e => 1)")
tryAndPrint("template", "String.raw `a\nb`")
tryAndPrint("generator", "(function* gen(){})")
tryAndPrint("expo operator", "3 ** 4")
tryAndPrint("for of", "for(var i of [99]) i")
tryAndPrint("async function", "(async function f(){})")
tryAndPrint("default param", "(function(a = 1){})")
tryAndPrint("... operator", "[...[1]]")
tryAndPrint("method definition", "({method(){}})")
tryAndPrint("object initializer", "var oi = 100;({oi})")
tryAndPrint("object key expression", "({['a' + 'b']: 1})")
</script>
Chrome で実行するとエラー無しでこうなります
Map.toString
"function Map() { [native code] }"
Set.toString
"function Set() { [native code] }"
fetch.toString
"function fetch() { [native code] }"
Array.from.toString
"function from() { [native code] }"
Promise.toString
"function Promise() { [native code] }"
let
undefined
const
undefined
typeof symbol
"symbol"
arrow function
undefined
template
"a\nb"
generator
undefined
expo operator
81
for of
99
async function
undefined
default param
undefined
... operator
[ 1 ]
method definition
{}
object initializer
{ "oi": 100 }
object key expression
{ "ab": 1 }
"function Map() { [native code] }"
Set.toString
"function Set() { [native code] }"
fetch.toString
"function fetch() { [native code] }"
Array.from.toString
"function from() { [native code] }"
Promise.toString
"function Promise() { [native code] }"
let
undefined
const
undefined
typeof symbol
"symbol"
arrow function
undefined
template
"a\nb"
generator
undefined
expo operator
81
for of
99
async function
undefined
default param
undefined
... operator
[ 1 ]
method definition
{}
object initializer
{ "oi": 100 }
object key expression
{ "ab": 1 }
console 出力じゃないので 文字列化するために JSON.stringify してます
その都合で関数は なくなりますが エラーが出てないなら使えていると判断できます
これを Fetch as Google にかけると

小さくて見づらいのですが Unexpected token となっているものが多いです
まとめると
Fetch as Google で使える
- Map, Set, Promise, Symbol 関数
- let, const 宣言
- テンプレートストリング (`)
- generator (function*(){})
- for-of
Fetch as Google で使えない
- Array.from 関数
- アロー関数
- ** 演算子
- async 関数
- 関数のデフォルトパラメータ
- ... 演算子
- メソッド定義構文 ({method1(){}, method2(){}})
- 変数名そのままのキーでオブジェクト作成 ({a, b, c})
- オブジェクトのキーに式を書く ({[1+1]: 100})
というところ
まだ試してない機能もいろいろですが 使える基準がよくわかりません
polyfill 可能な関数は使えて 構文はダメ ならわかりやすいのですけど for-of や let はつかえますし Array.from は使えません
navigator
もしかすると古い Chrome を使っていて そのバージョンの対応してたものだけかも と思ったので navigator を確認してみました<!doctype html>
<meta charset="utf-8">
<style>pre{width:600px;white-space:pre-wrap;}</style>
<div></div>
<script>
function add(title, contents){
var h1 = document.createElement("h1")
h1.innerHTML = title
var pre = document.createElement("pre")
pre.innerHTML = JSON.stringify(contents, null, " ")
var hr = document.createElement("hr")
document.body.appendChild(h1)
document.body.appendChild(pre)
document.body.appendChild(hr)
}
var obj = {}
var navigator_keys = [
"appCodeName",
"appName",
"appVersion",
"cookieEnabled",
"credentials",
"doNotTrack",
"geolocation",
"hardwareConcurrency",
"language",
"languages",
"maxTouchPoints",
"mediaDevices",
"mimeTypes",
"onLine",
"permissions",
"platform",
"plugins",
"presentation",
"product",
"productSub",
"serviceWorker",
"storage",
"userAgent",
"vendor",
"vendorSub",
]
navigator_keys.forEach(function(e){
obj[e] = navigator[e]
})
add("navigator", obj)
</script>
<meta charset="utf-8">
<style>pre{width:600px;white-space:pre-wrap;}</style>
<div></div>
<script>
function add(title, contents){
var h1 = document.createElement("h1")
h1.innerHTML = title
var pre = document.createElement("pre")
pre.innerHTML = JSON.stringify(contents, null, " ")
var hr = document.createElement("hr")
document.body.appendChild(h1)
document.body.appendChild(pre)
document.body.appendChild(hr)
}
var obj = {}
var navigator_keys = [
"appCodeName",
"appName",
"appVersion",
"cookieEnabled",
"credentials",
"doNotTrack",
"geolocation",
"hardwareConcurrency",
"language",
"languages",
"maxTouchPoints",
"mediaDevices",
"mimeTypes",
"onLine",
"permissions",
"platform",
"plugins",
"presentation",
"product",
"productSub",
"serviceWorker",
"storage",
"userAgent",
"vendor",
"vendorSub",
]
navigator_keys.forEach(function(e){
obj[e] = navigator[e]
})
add("navigator", obj)
</script>
navigators のキー一覧は enumerable:false のようで取れないので 今の Chrome にあるものを直接指定しました
まずは Chrome 56 のときの場合
{
"appCodeName": "Mozilla",
"appName": "Netscape",
"appVersion": "5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"cookieEnabled": true,
"credentials": {},
"doNotTrack": null,
"geolocation": {},
"hardwareConcurrency": 8,
"language": "ja",
"languages": [
"ja",
"en-US",
"en"
],
"maxTouchPoints": 0,
"mediaDevices": {},
"mimeTypes": {
"0": {},
"1": {},
"2": {},
"3": {},
"4": {},
"5": {},
"6": {}
},
"onLine": true,
"permissions": {},
"platform": "Win32",
"plugins": {
"0": {
"0": {}
},
"1": {
"0": {}
},
"2": {
"0": {},
"1": {}
},
"3": {
"0": {},
"1": {}
},
"4": {
"0": {}
}
},
"presentation": {},
"product": "Gecko",
"productSub": "20030107",
"serviceWorker": {},
"storage": {},
"userAgent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"vendor": "Google Inc.",
"vendorSub": ""
}
"appCodeName": "Mozilla",
"appName": "Netscape",
"appVersion": "5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"cookieEnabled": true,
"credentials": {},
"doNotTrack": null,
"geolocation": {},
"hardwareConcurrency": 8,
"language": "ja",
"languages": [
"ja",
"en-US",
"en"
],
"maxTouchPoints": 0,
"mediaDevices": {},
"mimeTypes": {
"0": {},
"1": {},
"2": {},
"3": {},
"4": {},
"5": {},
"6": {}
},
"onLine": true,
"permissions": {},
"platform": "Win32",
"plugins": {
"0": {
"0": {}
},
"1": {
"0": {}
},
"2": {
"0": {},
"1": {}
},
"3": {
"0": {},
"1": {}
},
"4": {
"0": {}
}
},
"presentation": {},
"product": "Gecko",
"productSub": "20030107",
"serviceWorker": {},
"storage": {},
"userAgent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36",
"vendor": "Google Inc.",
"vendorSub": ""
}
Search Console だと
{
"appCodeName": "Mozilla",
"appName": "Netscape",
"appVersion": "5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
"cookieEnabled": true,
"doNotTrack": null,
"geolocation": {},
"hardwareConcurrency": 1,
"language": "en-US",
"languages": [
"en-US"
],
"maxTouchPoints": 0,
"mimeTypes": {
"length": 0
},
"onLine": true,
"platform": "Linux x86_64",
"plugins": {
"length": 0
},
"product": "Gecko",
"productSub": "20030107",
"userAgent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
"vendor": "Google Inc.",
"vendorSub": ""
}
"appCodeName": "Mozilla",
"appName": "Netscape",
"appVersion": "5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
"cookieEnabled": true,
"doNotTrack": null,
"geolocation": {},
"hardwareConcurrency": 1,
"language": "en-US",
"languages": [
"en-US"
],
"maxTouchPoints": 0,
"mimeTypes": {
"length": 0
},
"onLine": true,
"platform": "Linux x86_64",
"plugins": {
"length": 0
},
"product": "Gecko",
"productSub": "20030107",
"userAgent": "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
"vendor": "Google Inc.",
"vendorSub": ""
}
bot という情報しかわかりません
諦めかけたのですが これまで違いがなかった左右で結果が変わっていました
右側の結果はこうなっていました
{
"appCodeName": "Mozilla",
"appName": "Netscape",
"appVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Search Console) Chrome/27.0.1453 Safari/537.36",
"cookieEnabled": true,
"doNotTrack": null,
"geolocation": {},
"hardwareConcurrency": 1,
"language": "en-US",
"languages": [
"en-US"
],
"maxTouchPoints": 0,
"mimeTypes": {
"length": 0
},
"onLine": true,
"platform": "Linux x86_64",
"plugins": {
"length": 0
},
"product": "Gecko",
"productSub": "20030107",
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Search Console) Chrome/27.0.1453 Safari/537.36",
"vendor": "Google Inc.",
"vendorSub": ""
}
"appCodeName": "Mozilla",
"appName": "Netscape",
"appVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Search Console) Chrome/27.0.1453 Safari/537.36",
"cookieEnabled": true,
"doNotTrack": null,
"geolocation": {},
"hardwareConcurrency": 1,
"language": "en-US",
"languages": [
"en-US"
],
"maxTouchPoints": 0,
"mimeTypes": {
"length": 0
},
"onLine": true,
"platform": "Linux x86_64",
"plugins": {
"length": 0
},
"product": "Gecko",
"productSub": "20030107",
"userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko; Google Search Console) Chrome/27.0.1453 Safari/537.36",
"vendor": "Google Inc.",
"vendorSub": ""
}
Chrome27 !
Google ってセキュリティがどうこういう割には古いの使ってるんですね
まとめ
Fetch as Google は Chrome 27 で動いてるのでそのときに使えなかった ES6 以降の機能は使えませんあくまで右側の 「あなたのサイトはこう見えてます」 の方で 「Googlebot はこう認識しました」 の方ではありません
ただ ES6 の対応具合などいくつかのパターンを試してみても navigator 以外は全く一緒の結果なので Chrome 27 と考えて大丈夫かと思います
COMMENT
コメント一覧 (4)
-
- 2017/10/12 13:39
-
こんにちは,初めまして.参考にしております.
自分のブログでもJavaScriptの実行をしてその結果をGoogle Botに読ませるということを考えています.
実際試したところGoogle Bot上では実行されていないのを確認したのですが,2017年10月現在でもGoogle BotはJavaScriptを実行して読み込んでいると考えていいのしょうか.
何か情報をご存知でしたら教えて頂けると幸いです.
-
- 2017/10/15 13:51
-
> 2017年10月現在でもGoogle BotはJavaScriptを実行して読み込んでいると考えていいのしょうか.
はい
今でも fetch as google での確認結果は JavaScript が適用されていますよ
どういうページかわからないのではっきりした原因はわかりませんが 特殊なことをしていなければ JavaScript でエラーが起きているのが一番可能性高いと思います
記事中にあるように Google Bot はそれなりに古いエンジンで実行されているようなので 今の Chrome では問題なくても Bot の実行ではエラーになっているかもしれません
-
- 2017/10/15 17:09
-
返信ありがとうございます。
詳細なエラーは見てないのですが,
try-catch 入る前の関数宣言の中にある"...operator"が原因でした(おそらく,SyntaxError).
やはり,GoogleBot上では,デバッグしにくいですね..
-
- 2017/10/15 21:50
-
構文エラーだと try-catch できないのでデバッグはしづらいですね
構文エラーとわかったあとにチェック用にこういうコードを設置してみるのもありです
try{
new Function(チェックしたい JavaScript のコード)
}catch(err){
document.body.style.whiteSpace = "pre"
document.body.textContent = err.message + "\n" + err.stack
}
また user-agent によると Chrome 27 なので Chrome 27 をインストールして動くことを確かめるのというのが準備は大変ですが一番原因が見つけやすいと思います
http://google-chrome.en.uptodown.com/ubuntu/old
過去のバージョンは↑などでダウンロードできます