◆ 登録したばかりだからかほとんど使えない
◆ Fetch as Google は JavaScript 実行するけどちょっと特殊
◆ アロー関数は使えない 

ライブドアのアクセス解析が新しくなってたのを見て そういえば Google Analytics を最初の頃に入れようとしてたのに結局忘れてて入れてなかったです

この機会に入れようかと調べていると 近い機能で Google 検索の結果を管理する Google Search Console というのを見つけました

ウェブページが Google からどう見えているかを確認する Fetch as Google や robots.txt の確認
インデックスされてるページの一覧やインデックスへの登録依頼に削除依頼ということもできるようです


ただ今のところ 登録してすぐだからか 何もできない機能が多いです

データがありません

とか

○○が完了していません

とか


とりあえず使えた Fetch as Google を使ってました

Fetch as Google を使うまで

Search Console は Analytics みたいな感じで 確認が必要なサイトの登録が必要です
誰でも見れるようにはなってないようです

(見れたほうが参考になりそうなのに)


登録するには ホームで自分のサイトのルートのパスを入力します
入力したら こんな画面になります

search-console3


自分のサイトだと証明するために この画面でダウンロードしたファイルをアップロードします
アップロードが終わったら「確認」を押して完了です

ライブドアブログだと HTML をアップロードできるのですが そういうことができない場合のために 他にも幾つか方法があります
Analytics を使ったり HTML のメタタグを追加したりです

Analytics を使ってるドメインの場合はオススメの方法が Analytics になりました

search-console2


登録が完了したらホーム画面に自分のサイトがでてきます

search-console1


ここをクリッククリックして サイトごとに情報を見たり編集したりすることができます

Fetch as Google の JavaScript 読み込み

Google は数年前から JavaScript も実行してくれるらしいので JavaScript で画面書き換えたのが表示されるか見てみます

いろんなタイミングで DOM 書き換えてみる

インラインのスクリプトや外部のスクリプトのロードでの書き換え
onload と DOMContentLoaded のイベントでの書き換え
fetch したあとの書き換え
document.writeln
for ループで 1 秒とめてみる

これらが入った html と js をアップロードして Fetch as Google の画面にその URL を入力すれば Google がページを読み込んでくれて結果がすぐに見れます

使ったコード

[search-console1.html]
<!doctype html>
<meta charset="utf-8"/>
<title>google search console test</title>

<script>
const $ = document.querySelector.bind(document)

document.addEventListener("DOMContentLoaded", eve => {
$("#dom-content-loaded").innerHTML = "DOMContentLoaded で変更されました"
}, false)

window.onload = eve => {
$("#onload").innerHTML = "onload で変更されました"
}

fetch("/").then(e => e.text()).then(e => $("#fetch").innerHTML = "fetch で変更されました")

</script>

<div>
<p id="html">ここはHTMLに含まれています</p>
<p id="dom-content-loaded">DOMContentLoaded で書き換えられます</p>
<p id="onload">onload で書き換えられます</p>
<p id="fetch">fetch で書き換えられます</p>
<p id="external">外部スクリプトで書き換えられます</p>
<p id="internal">インラインスクリプトで書き換えられます</p>
<p id="wait">for で 1 秒まって書き換えられます</p>
<script>document.writeln(`<p>javascript で出力されました</p>`)</script>
</div>

<script>
$("#internal").innerHTML = "インラインスクリプトで書き換えられました"

const date = Date.now()
while(date+1000>Date.now());
$("#wait").innerHTML = "for で 1 秒まって書き換えられました"

</script>
<script src="search-console1.js"></script>

[search-console1.js]
var elem = document.getElementById("external")
elem && (elem.innerHTML = "外部スクリプトで変更されました")
}()

さて 結果は

search-console4

あれ?
更新されてるのは writeln と外部スクリプトだけ……
左と右の違いがわかりませんが どちらも一緒です

ブラウザで見た場合はちゃんと全部更新されています

HTML 中に直接コードを書いてるインラインのスクリプトは無視されて 外部の .js ファイルをロードしたものだけ動くようにも見えますが writeln はインラインなんですよね

外部スクリプトに重い処理を持っていくと

もしかして for で 1 秒待つ なんて処理があるので重いから途中で止められたのかも? と思って 1 秒 for で待つ処理を外部スクリプトのほうにしてみました

[search-console2.html]
<!doctype html>
<meta charset="utf-8"/>
<title>google search console test</title>

<script>
const $ = document.querySelector.bind(document)

document.addEventListener("DOMContentLoaded", eve => {
$("#dom-content-loaded").innerHTML = "DOMContentLoaded で変更されました"
}, false)

window.onload = eve => {
$("#onload").innerHTML = "onload で変更されました"
}

fetch("/").then(e => e.text()).then(e => $("#fetch").innerHTML = "fetch で変更されました")

</script>

<div>
<p id="html">ここはHTMLに含まれています</p>
<p id="dom-content-loaded">DOMContentLoaded で書き換えられます</p>
<p id="onload">onload で書き換えられます</p>
<p id="fetch">fetch で書き換えられます</p>
<p id="external">外部スクリプトで書き換えられます</p>
<p id="internal">インラインスクリプトで書き換えられます</p>
<p id="wait">for で 1 秒まって書き換えられます</p>
<script>document.writeln(`<p>javascript で出力されました</p>`)</script>
</div>

<script>
$("#internal").innerHTML = "インラインスクリプトで書き換えられました"
</script>
<script src="search-console2.js"></script>

[search-console2.js]
var elem = document.getElementById("external")
elem && (elem.innerHTML = "外部スクリプトで変更されました")

var date = Date.now()
while(date+1000>Date.now());
var wait = document.getElementById("wait")
wait && (wait.innerHTML = "for で 1 秒まって書き換えられました")

}()

これで 外部スクリプトは書き換えられなくて その他が動けば予想どおり

さて結果は

search-console6

1 秒待っても外部スクリプトは動いています

どうして動くところと動かないところがあるんだろう?

ES6 ってもしかして

外部スクリプトを見ていて ふと ES6 (以降) が使われてないと気づきました
もしかすると Google だけどクローラは ES6 を処理できないのかも

でも writeln って ES6 のテンプレートストリング (`) 使ってるような……
まあ一応試してみよう

fetch ももしかしたら使えないかもなので なしにします

[search-console3.html]
<!doctype html>
<meta charset="utf-8"/>
<title>google search console test</title>

<script>
document.addEventListener("DOMContentLoaded", function(eve){
document.getElementById("dom-content-loaded").innerHTML = "DOMContentLoaded で変更されました"
}, false)

window.onload = function(eve){
document.getElementById("onload").innerHTML = "onload で変更されました"
}

</script>

<div>
<p id="html">ここはHTMLに含まれています</p>
<p id="dom-content-loaded">DOMContentLoaded で書き換えられます</p>
<p id="onload">onload で書き換えられます</p>
<p id="fetch">fetch で書き換えられます</p>
<p id="external">外部スクリプトで書き換えられます</p>
<p id="internal">インラインスクリプトで書き換えられます</p>
<p id="wait">for で 1 秒まって書き換えられます</p>
<script>document.writeln(`<p>javascript で出力されました</p>`)</script>
</div>

<script>
document.getElementById("internal").innerHTML = "インラインスクリプトで書き換えられました"
</script>
<script src="search-console3.js"></script>

[search-console3.js]
var elem = document.getElementById("external")
elem && (elem.innerHTML = "外部スクリプトで変更されました")

var date = Date.now()
while(date+1000>Date.now());
var wait = document.getElementById("wait")
wait && (wait.innerHTML = "for で 1 秒まって書き換えられました")

}()

今度こそ結果は

search-console5

動いてる!!

何がつかえないの

Chrome と同じ V8 で解釈してるのかと思ったら 違うみたいで ES6 以降の機能がダメそうでした
でも テンプレートストリングはできているし どれがだめなのか気になったので調べてみました

方法は単純にエラーを画面に出すだけ

[search-console4.html]
<!doctype html>
<meta charset="utf-8"/>
<title>google search console test</title>

<script>

var code = String.raw `
const $ = document.querySelector.bind(document)

document.addEventListener("DOMContentLoaded", eve => {
$("#dom-content-loaded").innerHTML = "DOMContentLoaded で変更されました"
}, false)

window.onload = eve => {
$("#onload").innerHTML = "onload で変更されました"
}

fetch("/").then(e => e.text()).then(e => $("#fetch").innerHTML = "fetch で変更されました")
`

try{
eval(code)
}catch(e){
document.writeln(e.message)
document.writeln("<br>")
document.writeln(e.stack)
}

</script>

<div>
<p id="html">ここはHTMLに含まれています</p>
<p id="dom-content-loaded">DOMContentLoaded で書き換えられます</p>
<p id="onload">onload で書き換えられます</p>
<p id="fetch">fetch で書き換えられます</p>
<p id="external">外部スクリプトで書き換えられます</p>
<p id="internal">インラインスクリプトで書き換えられます</p>
<p id="wait">for で 1 秒まって書き換えられます</p>
<script>document.writeln(`<p>javascript で出力されました</p>`)</script>
</div>

結果は

search-console7

Unexpected token =>

アロー関数が使えないようです
アロー関数を使わないようにするとあとは動きました

fetch や Promise や const は問題ないようです
なぜアロー関数だけだめなの……

fetch が遅かったらどうなるの

fetch で取得が遅かったらタイムアウトで実行されないのか気になりました

でも ライブドアブログではサーバサイドの処理はできません
Google から見れないといけないのでローカルにサーバを一時的に作っても意味ないです
しかたないので代わりに setTimeout を使ってみました
ネットワーク通信があったら待ってくれるとかの処理がなければ setTimeout でも一緒のはずです

[search-console5.html]
<!doctype html>
<meta charset="utf-8"/>
<title>google search console test</title>

<script>

window.onload = function(){
document.writeln("<div>" + Date.now() + "(onload)</div>")
}

fetch("/").then(function(e){return e.text()})
.then(function(e){
document.writeln("<div>" + Date.now() + "(fetch)</div>")
})

setTimeout(function(){
document.writeln("<div>" + Date.now() + "(timeout300)</div>")
}, 300)

setTimeout(function(){
document.writeln("<div>" + Date.now() + "(timeout600)</div>")
}, 600)

setTimeout(function(){
document.writeln("<div>" + Date.now() + "(timeout900)</div>")
}, 900)

setInterval(function(){
document.writeln("<div>" + Date.now() + "(1s)</div>")
}, 1000)

</script>

1 秒以降は setInterval で出力し続けます
こうなりました

search-console8

5 秒までは待ってくれるみたいです

そうなると JavaScript の処理自体が 5 秒超えるとどうなるのかも気になります

コードはこうなりました
最初に for 文で待ってます

[search-console6.html]
<!doctype html>
<meta charset="utf-8"/>
<title>google search console test</title>

<div></div>
<script>
function addDiv(html){
var div = document.createElement("div")
div.innerHTML = html
document.body.appendChild(div)
}

addDiv(Date.now() + "(start)")

var date = Date.now()
while(date+8000>Date.now());

addDiv(Date.now() + "(forend)")


window.onload = function(){
addDiv(Date.now() + "(onload)")
}

fetch("/").then(function(e){return e.text()})
.then(function(e){
addDiv(Date.now() + "(fetch)")
})

setTimeout(function(){
addDiv(Date.now() + "(timeout300)")
}, 300)

setTimeout(function(){
addDiv(Date.now() + "(timeout600)")
}, 600)

setTimeout(function(){
addDiv(Date.now() + "(timeout900)")
}, 900)

setInterval(function(){
addDiv(Date.now() + "(1s)")
}, 1000)

</script>

とりあえず 8 秒間 for で wait します
document.writeln で消えないように div を appendChild する方法にしています

結果は

search-console9

ちゃんと 8 秒まってくれています
でもその後の非同期処理が 1ms ごとに実行されています

8 秒待つ前に非同期処理を開始しているならわかりますが ここでは 8 秒待った後に非同期処理を開始しています
普通のブラウザなら 1 秒ごとに表示されるはずです

これを見ると 「5 秒」 じゃなくて setInterval は 5 回まで という制限のほうがありそうに思えてきます

アロー関数も使えなかったですし V8 とは違うクロール用の独自の JavaScript エンジンがあるのかもしれません
完全にブラウザ JavaScript との互換性があるわけではないので 動的に作られるコンテンツで Google 検索に出てくるようにしたいなら ページ読み込んだときにロード画面を出して JavaScript で一から DOM を作るのはやらないほうが安全なのかも