広告ブロック機能を使っている閲覧者には読めない記事を送信するアンチ広告ブロック

チラシおことわり
©いらすとや.

この記事は、嫌儲の方(自身の行為によりアカの他人が1円でも利益を得ることが許せない方)には到底納得できないであろう内容となっています。別のページまたは他所のサイトに移動されることをオススメします。

ウェブの広告は、「がとらぼ」の中の人が閲覧者であれば「まぁ見たくないけどどうでもいい。」程度。しつこく同じのが表示されたりセクシャルな画像だったり健康関係の広告の不快な画像、全ページ広告とかは「できれば見たくはない」そんな感じ。広告内容云々以前にハラの立つ行儀の悪い表示の広告もある。
でも、ウェブサイトを作って提供し続けるとなると、サーバのイニシャルコスト+月々の維持費さらにコンテンツを作るコストも。これが1ヶ月に1000円,2000円程度であれば全部自腹でも良いけど、維持費だけでも毎月万単位だといくら趣味でも全額自腹はツラい。たとえ微々たる額でも広告収入があれば助かるというか広告収入がないとやっていけないというもの。
そうなると、コンテンツを提供する側としては広告を見ることすら拒否してタダ読みをされるというのは困る。(コンテンツの有益性を棚上げしてスミマセン)
そこで広告ブロックアプリや広告をブロックするブラウザ拡張機能を使用している閲覧者にはコンテンツを表示しない、或いはもう少しソフトに「警告」を表示するという手段を講じることが必要になる(かもしれない)。

まぁ本来なら、「もしもこの糞下僕の拙い駄文でお目汚ししましたら誠に申し訳ございません。こんなコンテンツでも僅かでもお役に立てましたら恐悦至極に存じます。」という気持ちは持ち続けたいところではあるけど、現実にはそれどころじゃない。

閲覧者には「広告を見ない権利」はあるけどコンテンツ提供側にも「タダ読みを防ぐ権利」があると。

アンチ広告ブロックの記事とサンプル

↑のリストの最後の2つが新しく作ってみたもの。その内の上側「文字コードシフト式アンチ広告ブロック」はウェブサイト側は特に何かすることはなくて簡単なJavascriptを出力するだけ。閲覧者のブラウザでJavascriptが実行され、広告ブロックを判定して(広告ブロックしているなら)コンテンツの文字(漢字)を正常なものではなくす(読めなくする)というもの。「がとらぼ」でも7月末〜8月頭まで1週間ほど実際に試してみた。特に問題はなかったようだが、サーバからブラウザに正しいコンテンツを送信してブラウザ上で読めなくするというものなのでHTMLソースを読むなりJavascriptを無効にするなりコンテンツを異常にする処理を壊すなりすれば全く問題なく読めてしまうという問題がある。つまり「毒にも薬にもならない」程度の効果しかない。

「逆・文字コードシフト式アンチ広告ブロック」がこの記事の本題。これは、ウェブサイト側で「文字をずらす」という処理を施して送信し、閲覧者のブラウザ側で「広告ブロックが無効」ならJavascriptで(逆に文字をずらして)正しいコンテンツを表示するというもの。これはJavascriptを正常に実行しなければ正しく読めないので「広告すら表示しないでタダ読みする閲覧者の為すがままを許さない」というウェブサイト提供者側には一定の満足感が出るもの。
ただし、これを採用したからといって、閲覧者が「広告ブロック機能を無効にして正常にコンテンツを読もうとする」とか「広告をクリックしてくれるようになる」かというとそれは不明。むしろ最近は理不尽な人が増えてるので反感を買うことがあるかも

ここで言う「文字をずらす」(シフトする)というのは文字コード表で文字○個(指定分)プラス或いはマイナスした文字を表示するというもの。例えばアルファベットで「マイナス1シフト」するとB→Aのようにアルファベットの1つ前の文字になるのでIBMはHALになる。「プラス1シフト」するとB→CのようになるのでIBMはJCNになる。ひらがなだと「マイナス1シフト」すると「い」→「あ」のようになるし「プラス1シフト」すると「い」→「う」になる。漢字なども同様にシフトさせると別の文字になる。
なお、このページのサンプルではUTF-8で漢字の最初の「亜」という文字以降のコードポイントをシフトさせるようにしているので半角英数字や「かな」「カナ」などは文字が変わらない。漢字のコードポイントを1つだけシフトさせると異体字などの似た字になることが多いので頑張ればなんとか読めるか読めないか程度に書き換わる。あと、半角英数字をシフトさせるとHTMLタグなどが壊れてしまうので文章の体裁が崩れたり画像が表示されなかったりという点で困る。

ウェブページを1つずつHTMLコード手書きで作るならそこに記載するコンテンツ本文自体を文字シフトしてやらなくてはならないのでこれは後の修正が面倒だしシフトさせるのも何か用意してやる必要がある。でも、最近は1ページずつHTMLコード書いてなんてやってる人はほぼ居ないだろうと思うのでこの記事では対象外。
殆どは何らかのCMSを使ってるだろうし、中でもWordPress使ってる人が結構多いと思う。そこでWordPress用に文字シフト出力用のコードを書いた。WordPressの管理画面では正常な内容で記事の作成・編集が出来て正常な内容でデータを保存する。ページを出力するときに文字シフトして読めなくして閲覧者のブラウザに送る。

/WORDPRESSのPATH/wp-content/themes/使用しているテーマ/functions.php (次のコードをファイル最後に追記)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
add_filter('the_content', 'shift_content');
function shift_content($content) {
    $arrCont = mb_str_split($content);
    $arrCont = array_map('utf8_zenkaku_codePointShift', $arrCont);
    return implode($arrCont);
}

function utf8_zenkaku_codePointShift($str){
    $cP = mb_ord($str, "utf8");
    if ($cP > 0x4e9b) {
        $cP = $cP - 1;
        $str = mb_chr($cP, "utf8");
    }
    return $str;
}

PHP77.?以降で且つmbstringモジュールが有効でないと機能しない関数を使っています。

WordPressのテーマでthe_content()関数が使われている部分が書き換わります。つまりWordPressのコンテンツ(本文)部分を書き換えるフィルタです。記事のタイトルやページのヘッダ・フッタ・ウィジェットなどは書き換わりません。
shift_content()関数はWordPressのコンテンツ本文に書かれている全ての文字を1文字ずつ配列にしてarray_map関数で配列の要素それぞれ(つまり1文字ずつ)にutf8_zenkaku_codePointShift()関数の処理を実行しimplodeで配列内の全要素を再接続。つまり個々の文字をつないで文字列に戻す。それを出力として返す。
utf8_zenkaku_codePointShift()関数は受けた1文字のコードポイントが0x4e9c(UTF-8で「亜」という漢字)以降であればコードポイントを1つマイナス方向にシフトさせて返すだけの単純な内容。
結構面倒そうなことだけどPHPだとド素人でも超簡単にできる。

投稿記事だけ(WordPressでは普通の記事1つだけを表示する)に適用したい場合は、 shift_content() 関数内で is_singular() を使って分岐させる。このような分岐は何かしらした方が良さげ。

functions.phpはWordPressのテーマの核心部分で、これの変更をとんでもなく間違えるとウェブサイト全体が正常に表示されなくなるなど重大な問題が発生するかもしれません。十分にご注意ください。

シフトした文字を戻すJavascriptをページのフッタに挿入する。
/WORDPRESSのPATH/wp-content/themes/使用しているテーマ/footer.php (以下を最後の方の</body>の直前に挿入する)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<script>
  const adspace = document.querySelector('#adwidget');
  const mCont = document.getElementById('mainContent').innerHTML;
  var mAfter = [];
  var afCont = '';
  if( adspace.clientHeight === 0 ){
    arrCont = mCont.split('');
    for(var i = 0; i < arrCont.length; i++){
      if (arrCont[i].charCodeAt(0) >= 0x4e9c) {
        mAfter[i] = String.fromCharCode(arrCont[i].charCodeAt() + 1);
      } else {
       mAfter[i] = arrCont[i];
      }
    }
    afCont = mAfter.join('');
    document.getElementById('mainContent').innerHTML = afCont;
  }
</script>

このJavascriptの中で、#adwidgetというのが広告のあるブロックを想定。必要に応じて変更。

このJavascriptの中で、mainContent(2箇所)というのがコンテンツ本文のブロックを想定。必要に応じて変更。

このJavascriptをどのように出力するかという処理を入れるのは当然考慮すべきこと。WordPressの「投稿記事」(ようするに普通の記事を1つだけ表示)のときだけこのJavascriptを出力するというような処理はあった方が良いが、好みで。もちろん、コンテンツ書き換え側もセットで。(読めないように書き換えたにも関わらずJavascriptが無かったら読めないままだし、本文を書き換えていないのにこのJavascriptを出力すると正常なコンテンツを異常にしてしまうので)

広告コードの部分 (Adsenseなら自動広告ではなくレクタングルのユニットなど)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<div id="adwidget">
<!--ここから広告コード -->
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
	style="display:block; text-align:center;"
	data-ad-layout="in-article"
	data-ad-format="fluid"
	data-ad-client="ca-pub-0000000000000000"
	data-ad-slot="0000000000"></ins>
<script>
	(adsbygoogle = window.adsbygoogle || []).push({});
</script>
<!--ここまで広告コード -->
</div>

広告コードを1行目の<div id="adwidget">と14行目の</div>で囲んでやることが重要。その id="adwidget" というのがJavascript内の#adwidgetのこと。この#adwidgetブロックの高さが0になったら広告が表示されていないという判断にする(Javascriptの方に書いてる)

コンテンツ本文は上のサンプルでは#mainContentであるということになっている。つまり書き換えられるブロックは<div id="mainContent">書き換えられる記事本文部分</div>という風になることを想定している。投稿記事(ようするに普通の記事を1つだけ)を表示するのであればテーマのファイルは /WORDPRESSのPATH/wp-content/themes/使用しているテーマ/template-parts/content/content-single.php (このPathは最近のWordpress標準添付のテーマの流儀と同じ場合) の中のthe_content();の周囲でid指定できそうなdivタグを見つけてid="mainContent"を指定する。(例: <div class="entry-content" id="mainContent">)

最近のGoogleさんはとても賢いのでこのようなコンテンツの書き換えが行われても表示完了時に正常な表示になるのであれば正常にクロールしてくれる筈だけど絶対とはいえないので自己責任で。

2022年5月12日追記:
Googleにインデックスされた記事本文が文字シフト(文字化け)した状態であることが判明。Chromeブラウザでページをレンダリングした状態でコンテンツとして認識した内容をインデックスするという話だったと認識していたがそうではないみたい。

2022年3月2日追記:
このページの広告ブロック機能は結構過激なので実ウェブサイトでの採用は見送っていましたが、微修正してこの「がとらぼ」に実装して運用をはじめました。「がとらぼ」の中でブログ記事だけに適用されます。WordPressでいう「固定記事」とスマホなどのモバイル系記事には適用されません。
2022年5月12日にこの文字コードシフト式アンチ広告ブロックの運用は中止。(他の方式のアンチ広告ブロックを採用することがあります)

関連記事: