広告タグの一括管理とかで、scriptタグの中にscriptタグを書きまくる運用ってけっこうあるかもしれない

サイト運用をしてると、必ず必要になってくることがある。コンテンツとかサイト構造とかの話じゃなくて、タグの話。

「Googleのリターゲタグ貼っといて」「ヤフーのコンバージョンタグ、このページだけに貼っといて」「なんかよくわからんけどアドネットワークのタグ貼ってくれって代理店に言われてるから貼っといて」「とりあえずGAのタグ入れてよ」みたいな依頼って、よくある。

別に俺じゃなくても担当者が勝手に入れればいいんだけど、それだとカオスになるし、そもそもHTMLやJSをよくわかってない人たちはサイトのソースに手を入れることを嫌うから(大手サイトになるとそれすらできないので、運用が触っていいインクルードHTMLとJSとCSSが一個ずつあってそこだけ管理下にある状態といのもある)、引き受ける場合が多い。

小さいサイトやソースを直接さわれるところだと、フッターテンプレートにもらったタグをそのまま貼り付ければ完了。

でもそういかない場合って、けっこうある。まじで。

たとえば、大手サイトだったり、クライアントサイトだったり、タグ入れ依頼がバケツリレーになってる状態だったり。
そうなると、サイトに手を入れるのが怖い・または時間がないクライアント様にこのチンケなタグを入れてもらうために労力を割いていただくのが申し訳ないので、ソリューションとしてはワンタグ運用が現実的になってくる。

ワンタグとは、1つのスクリプトタグをサイトに入れてもらい、そのスクリプトの中身を一括で管理するやり方だ。これなら、クライアントサイトであっても一回だけタグを入れてもらえれば、タグの中身はこっちでできるので心配が少ないし、いざとなったらスグに書き換えできるので運用もやりやすい。
ただしワンタグ運用は2つの問題が起こる。
1.全ページに同じワンタグを貼る前提になること
2.各アドタグをすべてこのワンタグに入れ込む必要があること


1については、URLやパラメータを見て「今はどのページなのか」をスクリプト側で判定するロジックを持たなければいけない。特にエントリーフォームとトップページでこの問題が起こる。トップページはいろんなサイトからいろんなパラメータ付でリンクが来るうえに、index.htmlがあったりなかったり、コントローラーアクションがなかったりするので、本当にトップかを判断するのはちょっとメンドイ。
さらにエントリーフォームでも、/form,/confirm,/finishみたいにURLベースでわかるものならいいが、/input.phpだけで全部のアクションがある場合はカオスだ。タイトルタグやメタタグ、H1なんかもDOMを見てページ状態を把握しなければいけない。
同じ問題で、「このカテゴリはAのリターゲタグ、あっちのカテゴリはBのリターゲタグ」という場合もURLまたはサブディレクトリの名前一致で判定しないといけない。

2については、ワンタグはscriptタグなのでJSだ。その中に、ほかのタグ用のJSを入れる必要があるということは、入れるタグを書き換える必要があるということだ。パターンとしては2つ。
・IMGタグの場合:全体を1つのstringにしてdocument.writeで書き出す
・外部scriptタグの場合:scriptタグ自体をdocument.writeで書き出す
大前提として、noscriptは無視する。媒体屋からnoscriptも頼んます、と言われても無視。

で、上の2パターンでは問題が起こりやすいのはもちろん後者だ。
あ、ちなみに「document.writeはレンダリングブロックするからフロントエンド最適化上リスク高いよ」という話はわかった上であえてこうしている。だって楽なんだもん。ちなみにdocument.write否定派に向けては記事の一番最後に対応策書いてるので下まで見てね。

特にこんなケースは注意が必要。

scriptとその呼び出しを一枚のscriptの中で行うケース

■本来のアドタグ
<script type="text/javascript" src="http://xxx.com/js/ad.js"></script>
<script type="text/javascript">
var _ad_vars1 = "hoge";
setAdHoge();
</script>

■scriptに入れる場合のタグ
document.write('<script src="//www.xxx.com/js/ad.js">\x3c/script>');
document.write('<script>var _ad_vars1="hoge";setAdHoge();\x3c/script>');

■間違ったやり方
document.write('<script src="//www.xxx.com/js/ad.js">\x3c/script>');
var _ad_vars1 = "hoge";
setAdHoge();

ここでは、2つのscriptをscriptに入れようとしている。
1つ目は広告媒体のタグそのものの読み込み、2つ目は読み込んだタグに変数をセットして、タグ内の関数を呼び出している。
間違ったやり方は、外部タグだけをdocument.writeしているが、これはNGだ。なぜなら、document.writeしたものは自身のタグよりもDOM上で下の位置に書き出されるため、setAdHoge()のコールがタグ読み込みよりも前に実行されてエラーになってしまう。

ちなみに、前時代的な「\x3c」を使ってるけど、いまはこれも必要ない。普通にシングルクオートにすればOK。

画像タグをscriptに書き換えるケース

■本来のタグ
<img src="http://xxx.com/adtag.gif?param1=abc&param2=def">

■scriptに入れる場合のタグ
var img_tag = '<img src="http://xxx.com/adtag.gif?param1=abc&param2=def">';
document.write(img_tag);

無駄な処理を書き換えるケース

これは本来は不要だが、スクリプトを発行するベンダー側がイケてない場合が多いので(アドエビスとかいまだにそうだよね)埋め込み上分かりやすくするもの。
httpとhttpsでドメインが同じならプロトコル見ないでプロトコルレラティブにしちゃえばいいよねという話。

■本来のタグ
if ( location.protocol == 'http:' ){
    strServerName = 'http://xxx.com';
} else {
    strServerName = 'https://xxx.com';
}
document.write("<scr" + "ipt type=\"text\/javascript\" src=\"" + strServerName + "\/tag.php?param...\" + \"><\/scr" + "ipt>");

■scriptに入れる場合のタグ
document.write("<scr" + "ipt src=\"//xxx.com/tag.php?param...\" + \"><\/scr" + "ipt>");

document.writeしない場合はどう書くか?

結論から言うと、scriptはheadにinsertし、imgはリクエストを飛ばすだけだ。
ただ、scriptはheadに埋めてしまうのはチョット怖い気がする。広告タグ側でdocument.writeしてるかもしれないし、DOM操作するかもしれないし。

//IMGタグを埋め込む
■scriptに入れる場合のタグ
var img_tag = '<img src="http://xxx.com/adtag.gif?param1=abc&param2=def" width="1" height="1">';
document.write(img_tag);

■scriptに入れる場合のタグでイケてる書き方
var srcPath ='//xxx.com/adtag.gif?param1=abc&param2=def';
var img = window.document.createElement('img');
img.width = '1';
img.height = '1';
img.src = srcPath;
//document.write(img) ←writeしなくてもリクエストが飛ぶのでよしとする

//Scriptタグを埋め込む
■scriptに入れる場合のタグ
document.write('<script src="//xxx.com/adtag.js"></script>');

■scriptに入れる場合のタグでイケてる書き方
var s = document.createElement('script');
s.src = '//xxx.com/adtag.js';
document.getElementsByTagName('head')[0].appendChild(s);

 

この記事には、カテゴリ javascript がつけられています。