リンクが表示されない？広告ブロック入れてませんか？

#初めに
**※この記事は広告ブロックの是非を論じるものではありません。**

先日、私が開発に関わった web のサービスでちょっとした問題が起こりました。

一部のユーザーが「ボタンが見当たらない。」というのです。

ページ内にはボタン(正確にはボタンっぽ見た目になるようにした種々の html タグ)がいくつか存在していましたが Twitter web intents URL の設定された `<a>` が消失しているようで、事象発生時のスクリーンショットも報告されていました。

***

## Twitter web intents
このサービスは Twitter との連携を強く意識しており、ページには Twitter web intents という、ツイート内容があらかじめ書き込まれた Twitter 公式ページへと遷移するリンクが設定されたボタンが用意されていました。

****

実際にどのような画面に遷移するかは [Twitter web intents 公式ドキュメント](https://developer.twitter.com/en/docs/twitter-for-websites/tweet-button/guides/web-intent) に web intent のサンプルリンクが用意されているので踏んでみましょう。

え？見に行ったけどそんなリンク見当たらなかった？わかりにくくて見つからないとかじゃなくて？
広告ブロックつけてませんか？

****

## ボタンが消えた理由
さて、この時我々はこの問題に遭遇してしまっているユーザーと直接やり取りをできているわけではありませんでした。
Twitter 上でユーザー間で問題の共有が行われている場面を発見しただけです。

問題の再現が手元で行えないので調査が難航していたところ、またしても一部のユーザーが今度は問題の解決法を発見したくれたようです。

広告ブロック等をつけている場合、それを外すとボタンが出てくるらしい。

****

まさかただ Twitter へ遷移するだけのリンクが広告扱いされて潰されるとは思っていなかったため完全に盲点でした。

ちなみに Twitter web intents のリンクはこんな感じ
https://twitter.com/intent/tweet?text=hello%20world

これが広告ブロッカーにより排除されているらしい。
誤チェストにごわす

****

#広告ブロッカー
本題です。
この名称でどういったものかは推して知るべしですが、広告ブロッカーとはコンテンツ内に存在する広告の画像やリンクそのものを非表示にするアプリケーションです。

広告ブロック、広告ブロッカー、アドブロック、コンテンツブロッカーなどと呼称されます。

ユーザーの導入理由としては

- 誤クリックを誘う、あるいは単純に内容が不快な広告の除去
- 広告コンテンツのダウンロードを抑えることで、通信料・バッテリー消費を抑える

などといったものがよく上げられます。

また、昨今はユーザー独自のフィルタリングルールを定義することができるものなどが多数あります。
簡素なものですが広告ブロック機能を標準搭載しているブラウザなども近頃は存在します。

****

## では、どの広告ブロッカーの影響なのか
とりあえず、ユーザーがどのアプリを使用しているかは情報がなかったので適当に Android, iOS, PC ブラウザ拡張 の3環境において代表的な広告ブロッカーを導入してみましたが結果は芳しくありませんでした。

(Android: AdGuard, iOS: Adblock Plus, PC:uBlock Origin)

****

それに、近頃は広告ブロッカーを導入しているユーザーも決して少なくはない数でしょう。

ごく一部のユーザーにのみ問題が生じている時点で

- マイナーだが、強力な広告ブロッカーを使用しているユーザーがいる。
- アプリは一般的だが、強力なフィルタルールを定義しているユーザーがいる。

このどちらかだと考えました。

さらに言うと、複数の環境のユーザーで問題が発生していることと、強力ならそうそうマイナーなこともないのでは？との考えで後者の線で追うことにしました。

****

## フィルタルール
広告ブロッカーのブラックリストのようなもの。
どういったコンテンツを広告と、あるいはユーザーに有害であると判断して除去するかを規定したものです。

使用しなくても各広告ブロッカーのデフォルト設定である程度の広告は除去できるが、より強力あるいはより正確な広告ブロックを求めて使用される。

****

今回私が使用した広告ブロッカーはどれも Adblock Plus 形式 のルールを読み込めるらしい。
そのため、自身で定義することも可能ですがネット上の有志や開発者によって公開されているものもあります。

このフィルタルールという機能に目をつけいくつかのネット上に公開されたフィルタルールを試してみました。

****

# 実験
さて、先ほどから実際のサービスのスクショを張るのをためらって文章のみの退屈な記事を展開し続けているのでこのあたりで画変わりを試みましょう。

サービスを模した、以下の非常に簡素な HTML を用意し、PCブラウザでテストを行いました。

```html
<p>
    ご参加いただきありがとうございます。<br>
    以下のリンクよりツイートをお願いします。
</p>
「<a href="https://twitter.com/intent/tweet?text=hello%20world">ここからツイート</a>」
```

**スクショ**
![スクリーンショット 2021-05-19 010054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/bf93ad9b-8640-e8d5-d9d5-b5b142a021df.png)

****

## フィルタルールの適用
ここでは取り立てて名称を上げることは避けますが、某大型掲示板の特にアフィリエイトへ並々ならぬ恨みをお抱えの方々がよく使用しているフィルタルールのいくつかを試してみました。
(当記事ではフィルタルールの設定方法などは記載しません。)

その結果が1つのフィルタルールで以下のような状態になりました。

**スクショ**
![スクリーンショット 2021-05-19 010451.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/e1eb4214-6d43-b308-17f1-78d1289489df.png)

ここではテストページで確認をしていますが、実際には自身のサービスでも状況の再現を確認しています。

****

というわけで、今回の原因は「一部フィルタルールのキルリストに捉えられてしまった」でしょう。
ここに来るまで結構時間がかかった。


さて、やはり犯人は広告ブロッカーだった。

ユーザーには広告ブロックを切ってねと案内しよう、めでたしめでたし。

****

とはなかなかならないもので、できれば回避したい。だって広告じゃないし。
小手先では回避できないとなったら初めて、「広告ブロック切って♡」と案内したい。

もともと広告ブロックを入れているユーザーは広告に忌避感を持っているのは間違いないでしょう。
それを表示できる状態にしてくれ、といった時点で嫌がられてしまうのは必至。

広告収益のため、ユーザーの広告ブロックの使用を検知してコンテンツ表示のために広告ブロックの解除を要求するサイトの存在も手伝い難色を示される可能性は高いだろう。

****

おそらく方法は2つ

1. キルリストから逃れる
2. 除去に打ち勝つ

まぁ、ちょっと調べた程度で回避できるのであれば企業広告も手を打たないわけがないので、あまり期待はしていないが頑張ってみよう。

****

## リンク表示の試み

### 問題のフィルタ定義
回避方法を検討するために、今回当たりだったフィルタルールの中身を見てみます。

疑わしい記述はこのあたりでしょう

```
##a[onclick*="twitter.com/intent/tweet"]
##a[href*="//twitter.com/intent/tweet"]
~twitter.com##a[href*="twitter.com/intent/tweet"]
```

Adblock Plus filters の書き方に従っているものと思われます。

詳しいことはわからないが、ルール中に登場するいくつかの記号は以下のような意味があるらしい。
- `##` : 要素除去ルールを示す。
- `~` : これからドメイン名が始まっている場合そのドメイン内ではルールが適用されなくなる。
- `*=` : 含む、を意味する。(スタイルシートの記法)

つまりは上記のルールは

twitter.com 以外のドメインで `twitter.com/intent/tweet` を `href` に含んでいる `<a>` は除去対象。
`//twitter.com/intent/tweet` を含んでいる場合は twitter.com 上であっても除去対象。
また、`onclick` に `twitter.com/intent/tweet` を含んでいる場合も除去対象。
ということだろうか。

ツイートを介して自身のアカウントへの誘因を図れるため邪魔な要素と判断されているのか、このフィルタルールにはしっかりマークされてしまっているらしい。
弱った。仕方がないのでどうやって要素が除去されているのか探って、一旦そちらの解除に望みを託してみる。

### `<a>` には何が起こっているのか
肝心の `<a>` には何が起きているのだろうか。
ブラウザのデベロッパーツールで確認してみる。

![スクリーンショット 2021-05-19 013635.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/73381c3c-2247-723a-f030-6397ce88c3eb.png)

意外なことに `<a>` タグ自体は生き残っていた。
何かスタイルを当てられて非表示にされているらしい。

ここで開発者ツールのスタイルの部分に目を向けてみる。

![スクリーンショット 2021-05-19 014850.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/46e3735d-918d-f525-491a-95fbc8569397.png)

さっきフィルタルールで見たような内容が列挙された `injected stylesheet` なるものが目に映る。

どうやらブラウザ拡張によって挿入されたスタイルシートらしい。多分。

さらに下まで行ってみると。

![スクリーンショット 2021-05-19 015207.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/b3eea783-cc8e-95a3-be29-f16735d7614d.png)

`display: none !important;`
間違いなくこれである。

#### 何とか `display: none !important;` を上書きできないか。
`injected stylesheet` とやらで追加されたスタイルの優先度がどれほどのものか知らないが、上書きを試みてみる。

```html
<p>
    ご参加いただきありがとうございます。<br>
    以下のリンクよりツイートをお願いします。
</p>
「<a id="link" href="https://twitter.com/intent/tweet?text=hello%20world">ここからツイート</a>」

<link rel="stylesheet" href="style.css">
```

```css
a#link{
  display: inline!important;
}
```

超簡単
id 指定で上書きを試みる。

****

まぁ、こんなかんじ

![スクリーンショット 2021-05-19 032737.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/16d72ab9-f7f5-c383-8e1c-fb8b90808e79.png)

この程度では表示されるようにならなかっｔ
おや？

`display: none !important;` は打ち消されているっぽいぞ？
じゃあなんで見えないのか。
残念ながら私にはわからなかった。

****

### `<a>` をやめる
というか別の方法を検討した。
`<a>` が徹底的にマークされているので、`<a>` の使用をやめます。

適当な要素を置いて onclick で javascript を使ってページを開きました。

```html
<p>
    ご参加いただきありがとうございます。<br>
    以下のリンクよりツイートをお願いします。
</p>
「<span id="link">ここからツイート</span>」

<script>
    const link = document.getElementById('link');
    link.addEventListener('click', function(){
        window.open('https://twitter.com/intent/tweet?text=hello%20world', '_blank');
    });
</script>
```

ちょっとした id を与えただけの `<span>` です。これが表示されないようなら普通のページもほとんど崩壊してしまうでしょう。

****

**スクショ**

![スクリーンショット 2021-05-19 130546.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/7ace87b3-a04e-b55c-afba-6b64cf225f17.png)

目論見通りこれは表示されました。

そしてクリックすると、
![スクリーンショット 2021-05-19 130853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315470/0a9f139e-0e65-f51d-cb4f-14eb5f08e2ce.png)

目標達成。
後は `<span>` に適当なスタイルを当ててボタンっぽくするといいはず。(本題ではないのでここではやらない。)

****

# 最後に
全く広告とは関係のない外部リンクが広告ブロッカーに除去されるとは思ってもみませんでした。
ネット上には多くのフィルタルールが共有されており、またそれらは新たな広告表示の手法に対応すべく日夜更新されています。

知識のある方には自身でルールを定義している方もいるでしょう。

広告ブロッカーを事前に完全に回避するのは至難の業かもしれません。

ある日突然一部のユーザーから、web ページの不調の知らせが届いた場合は広告ブロッカーを疑ってみる必要があるかもしれません。

念のためもう一度
**※この記事は広告ブロックの是非を論じるものではありません。**

****

# 参考資料
[AdBlock Plus - How to write filters](https://help.eyeo.com/en/adblockplus/how-to-write-filters)