| @ブログ

シダの新緑
シダの新緑

最近、ブログに Amazon アソシエイトの広告が表示されなくなっていた。記事の新規公開時だけでなく、最新の価格情報を取得するため 24 時間のみキャッシュして都度新しいデータをとるようにしていたが、商品が 30 日間売れなかったため API へのアクセス権を剥奪されてしまったようだ。アフィリエイト報酬がもらえないのもさみしいが、それよりも記事に商品の画像を表示出来ないのが悲しい。結構頑張って仕組みを作ったのに。

ドキュメントには以下のように書いてあった。

Note that your account will lose access to Product Advertising API 5.0 if it has not generated referring sales for a consecutive 30-day period.

API Rates · Product Advertising API 5.0

これはかなりきびしい。 30 日間でものが売れないことなんてザラにある。 ものが売れない -> API のアクセス権剥奪 -> 商品情報取得できない -> ものが売れない の負のスパイラルに陥ってしまうので基本的には抜け出すことはできない。

Google Adsense といい、個人の泡沫ブログで小銭を稼ぐのがどんどん難しくなっていく。

| @ブログ

Composing HEY World
Composing HEY World

メールを送るだけでブログを書ける HEY World はとても体験が良い。入力しなければならないのはタイトルと本文だけ。カテゴリーやタグを選んだり、公開時の URL を選んだり、日付を設定したりできない。しかしそのせいで内容に集中できる。

ブログは万年筆のように書き味が大事だと思う。 HEY のメール作成画面は飛び抜けて良いわけではないが、ほどほどに良い。残念ながらこのブログの投稿欄よりも良いのは確実。別のエディターで下書きして貼り付ける手間がなく、いきなり書いて Send ボタンを押すだけでブログを公開できるのはとにかく便利。下書きはメールの下書きとして保存すればよく、出来上がったら world@hey.com に対してメールを送信する。ブログを書きたいけど管理画面にログインするのが面倒くさいとか、小さなフォーム入力欄で文章を書くのがかったるいというような、ブログを書くための障害をあらかた取り除いている。

メールはスパムによって程度の低い通信手段にされてしまったが、メールによって情報発信をする手法は見直されて良いと思う。昔はモブログという概念があって、ガラケーからメールでブログ投稿できる機能を備えてるブログサービスがあった。このブログにもメール投稿の機能を付けてみたいと思った。

| @ブログ

※いまブログに広告を表示されてる方たちを攻撃する意図はないです

高尚なことが書かれてるブログに、手のしみとりとか豊胸とかエログロ漫画の低俗広告が表示されてると、どんなに立派なことが書いてあっても説得力を感じなくなってしまう。

自分も一年前まではブログに広告を出していた。

広告の表示はやめて本当によかったと感じる。いまからもう一度広告を表示する気にはなれない。

広告を表示していた頃は、低俗広告がいかにコンテンツ内容を毀損していたかということに気が付けていなかった。何か大事なことをシリアスに書いていても、そのすぐ脇に発毛剤とか精力剤とかエロゲームの広告が表示されていたらそれはギャグでしかない。

そもそも自分のブログの一番の読者は自分であり、広告を表示することで自分自身が見ても一円の得にもならない低俗な広告を延々見せられ続け、無料で広告を表示できて広告主が得をするだけだ。

半年に一度数千円もらうために記事内容を毀損するような低俗広告を表示するのはトータルで考えるとむしろ損だ。モチベーションを維持するために金銭的な報償が必要なのであれば、アドセンス広告よりも GitHub Sponsors とか、懐に余裕がある人からの支援を募った方が良いと思う。 Hail2u.net のながしまきょうさんがこの手法をとっていてなるほどと思った。コードを書かない人であれば Gumroad とか Patreon とかにすればいいし、 Amazon のウィッシュリストを掲載するのでも良いと思う。

広告によって無料でいろんなものを提供するのは、少額決済の仕組みがなかった時代に苦肉の策で生み出された手法だ。いまは 100 円、 200 円でもインターネット越しにお金を集めることができる。コンテンツを提供する側はたとえ個人のブログであったとしても安易に広告で収益を得ようとするのをやめて、お金が必要なのであれば真剣にマネタイズと向き合う必要があるだろう。

| @ブログ

iPad を持っていないので確認していなかったのだけど、タブレットなど狭めの横幅のブラウザーでこのサイトのインデックスページを見ると残念な感じになっていたのでいい感じに調整した。横幅 1113px 以上だと past-entries セクションが 3 カラム表示になり、 1112px 以下だと 2 カラム表示に、 640px 以下だと 1 カラム表示になるようにした。これまでは 640px 以下のときの 1 カラム表示対応しかなくて、横幅が狭いブラウザーで見たときに悲惨なことになっていた。

デスクトップ表示
デスクトップ表示

タブレット表示
タブレット表示

スマートフォン表示
スマートフォン表示

その他、フッターの人気記事表示を変更した。インデックスページに最近の人気記事とはてブでホッテントリ入りした記事を表示するようにしたので、同じコンテンツがフッターにあるのは無駄だと感じた。かわりにフッターには今日と昨日の人気記事を表示するようにした。

今日の人気記事と昨日の人気記事
今日の人気記事と昨日の人気記事

よく読まれる記事の傾向はその日その日で結構違う。新しい記事を書くと当然その記事にアクセスが集まるのだけど、しばらく何も書いていないと意外な記事がアクセスを集めてたりして発見がある。例えば最近では Flickr の有料化についての記事がアクセスを集めていたが、 Google Photos の有料化が発表されたからだった。いっぱい記事を書いておくと、自分のブログへのアクセス傾向から世の中の動きが確認できて便利だ。

| @ブログ

インデックスページにカテゴリーへの導線を作るべきということを書いたがさすがにラディカル過ぎた。

インデックスページのコンテンツ数が増え、ページの応答速度が 800ms ほどになっていた。 DOM サイズも大きくなり、転送量が増えてユーザーフレンドリーではないなと思った。確かにユーザーの回遊性は高まるかもしれないが、ページがごちゃごちゃしていて快適ではない。これではブログサービスでブログをやっているのと大差ないと思い直し、インデックスページの記事数を最小限に絞った。

少しシンプルになったインデックスページ
少しシンプルになったインデックスページ

全カテゴリーの最新記事の表示はやめ、最新の 7 記事だけ表示するようにした(最新の記事だけ大きく表示するというスタイルは残している)。カテゴリー一覧ごとの最新記事は別途 カテゴリー一覧ページ を用意してそちらに移した。

またページ下部に最近閲覧数が多い記事とはてブでホッテントリ入りした記事へのリンク1を付けた。これまではフッターに表示していたが、フッターのリンクはあまりクリックされていない疑惑があるし、結構面白コンテンツだと思うのでインデックスページのメインコンテンツとしてしつらえることにした。そもそも 21 世紀のブログでフッターなんてものはいらないのかもしれない。

人気記事一覧
人気記事一覧

シンプルにしたインデックスページは応答速度が 200ms を切っていてまぁまぁ高速で Google PageSpeed Insights でも 90 点くらいを取れる。個人ブログなのでシンプリシティは大切にしたい。

| @ブログ

インデックスページをいじって各カテゴリーの最新記事 4 件を配置するようにしてみた。最近の個人サイト復興ブームでみなさんインデックスページを工夫されているのを見ていて真似したくなってやった。

カテゴリーごとに最新記事 4 件を表示
カテゴリーごとに最新記事 4 件を表示

昔ながらのブログだとインデックスページというのは最新の記事 10 件くらいが表示されていて、「次へ」を押すと古い記事が出てくるという構成になっている。以前のこのブログもそうだった。

しかし自分自身が他人のブログで「次へ」を押して次々に記事を読んでいくということをやった記憶がほとんどない。自分のブログでだって何か目的があって特定のキーワードで検索したあとに引っかかった記事を読むという感じなので、時系列に本文とセットで記事が 10 件ずつ表示される UI というのは意味をなしていないと思った。そもそもインデックスという名称なのに最近の記事数件しか表示していないのはおかしい。インデックスというからにはすべての記事の目次になるべきだ。

このブログはカテゴリーがあるので、サイトマップを作るとするとこんな感じになると思う。

+----------+        +------------+        +-----------+
|          |        |            |        |           |
|   Blog   +---+--->+  Category  +------->+   Entry   |
|          |   |    |            |        |           |
+----------+   |    +------------+        +-----------+
               |
               |
               |    +------------+        +-----------+
               |    |            |        |           |
               +--->+  Category  +---+--->+   Entry   |
                    |            |   |    |           |
                    +------------+   |    +-----------+
                                     |
                                     |
                                     |    +-----------+
                                     |    |           |
                                     +--->+   Entry   |
                                     |    |           |
                                     |    +-----------+
                                     |
                                     |
                                     |    +-----------+
                                     |    |           |
                                     +--->+   Entry   |
                                          |           |
                                          +-----------+

第一階層がインデックスページで、第二階層がカテゴリートップ、そして各記事がある。なのでインデックスページは二階層目の一覧ページになっているのが望ましいはずだ。しかし伝統的なブログはカテゴリーという記事をまとめる概念がありつつも、インデックスページから各記事ページへ直接遷移するのが主な導線だった。常に最新の記事が時系列順に並んでいるだけでは味気ないし、常連の読者ではないコンテキストを知らない訪問者には不親切だろう。

しかも SNS の隆盛で個人のブログのインデックスページが参照される機会というのはとんとなくなってしまった。個人が書いたブログ記事は SNS 経由で読まれ、個別記事だけが読まれる。インデックスページやトップページが読まれることはほとんどない。 SNS でシェアされている URL をクリックして個別記事を読んで、それ以上そのブログのほかの記事を読むことなく離脱してしまう。前後のコンテキストは無視して、一つのコンテンツだけがつまみ食いされてしまう。そんな流れにあらがいたいと思った。

これまで関連記事を記事下に表示するなどやってきたが、気に入っていくつか記事を読んで「ホーム」( = インデックスページ)を訪れたユーザーがもう少しブログを深掘りしてみたくなるようにインデックスページを各カテゴリーの最新記事一覧とするようにしてみた。このブログは現在カテゴリーが 13 個あるので、それぞれから 4 件ずつ記事を取得すると 52 記事になる。全カテゴリーからまんべんなく 4 記事ずつ取得して表示するのは簡単なようで結構難しい。普通の SQL ではできない。 OR マッパーではまず無理だろう。

いろいろ調べてみた結果、 MySQL では GROUP_CONCAT というのが使えそうだった。以下のような SQL を書いた。

select entries.id
from entries
inner join (
  select
    category_id,
    GROUP_CONCAT(id order by created_at desc) as entry_ids,
    max(created_at) as last_created_at
  from entries
  where entries.draft = false
  group by category_id
) as grouped_entries
on grouped_entries.category_id = entries.category_id
and FIND_IN_SET(id, entry_ids) between 1 and 4
order by last_created_at desc, entries.id desc;

GROUP_CONCATFIND_IN_SET という関数を組み合わせることで、各カテゴリーから作成日の降順に記事を 4 件ずつ取得できた。このクエリでは記事 id のみ取得して、もう一回 DB に記事を取得するクエリを ActiveRecord で投げる。 ActiveRecord でクエリを組み立てるときは N+1 が起こらないように関連テーブルを JOIN する。

query = <<~SQL
  select entries.id
  from entries
  inner join (
    select
      category_id,
      group_concat(id order by created_at desc) as entry_ids,
      max(created_at) as last_created_at
    from entries
    where entries.draft = false
    group by category_id
  ) as grouped_entries
    on grouped_entries.category_id = entries.category_id
    and find_in_set(id, entry_ids) between 1 and 4
  inner join categories on categories.id = entries.category_id
  order by last_created_at desc, entries.id desc;
SQL
entry_ids = ActiveRecord::Base.connection.select_all(query).rows.flatten
entries = Entry.includes(:category, :user, :tags, :comments).where(id: entry_ids)

PostgreSQL のときに最初に取得した entry_ids の並び順通りに結果が受け取れるかは怪しいが、 MySQL の場合は一回目のクエリで取得した id 順に各レコードが ActiveRecord のクエリ結果として取得できた。あとはこれをカテゴリーごとにグルーピングして View でよろしくやれば良い。

なお各カテゴリーはカテゴリー内の最新の記事の作成日で降順ソートするようにしている。例えば現在のインデックスページの最下部には音楽カテゴリーがあるが、これは音楽についての記事を最後に書いたのが一年以上前だからだ。もしいま音楽の記事を書けば音楽カテゴリーがトップに浮上するようになっている。

見た目に関しては各カテゴリーの記事最新一件は大きなサイズで表示している。最も最近書かれた記事なのでより多く人の目に付いた方がよいだろうという考えだ。またすべての記事にサムネイルというか、アイキャッチ画像を表示するようにした。画像がない記事に関してはデフォルトのサイトアイコン画像を表示するようにしている。やっぱり視覚的に情報を捉えられるのは重要だ。画像がごちゃごちゃ表示されるのを嫌う人もいるかもしれないが、テキストだけでは人間の認知というのはどうしても追いつかない。

あわせて今回、インデックスページの冒頭部にこのサイトについての説明文を載せることにした。ながしまきょうさんr7kamura さんがやっているののパクりだ。伝統的なブログのインデックスページは初めて訪れた人のことを無視しすぎていたと思う。そのブログ自体について説明するページがあるブログは少ない。最初の記事でブログを始めた経緯みたいなことが書かれたきり、そのブログは何なのか、誰が書いているのかが書かれることは希だ。きちんとブログについての説明ページと著者についての説明ページがあっても、左右のサイドバーやトップのナビゲーションの端っこに押し込まれて見られることはない。これではいけないだろう。というわけでインデックスページの一番目立つ位置にブログと自分自身の簡単な紹介を入れた。

インデックスページトップに紹介文を表示
インデックスページトップに紹介文を表示

ブログはなぜ衰退したかを考えてみると、 Facebook や Twitter の隆盛はあるにせよ、ブログ自体に初めて訪れた人に読まれるための工夫が欠けていたのだと思う。誰も自分のブログの継続率を計測したりコホート分析したりはしない。読者が前後の記事を読んでいることを前提に書かれた記事やサイト構成では初めて訪れた人はどうやっても離脱してしまう。特に書き手が芸能人でもない一般人の場合はなおさらだ。誰も RSS フィードを購読していないし、ほとんどの読者は初めて訪れる人なのだから、そういう人たちが読んでブログのテーマや著者の人となりが分かる構成にしていかなければならないのだと思う。でないと SNS でたまにバズったときだけ読んでもらえる、ソーシャルメディアの肥やしにしかならない。

この新しいインデックスページが正解なのかどうかは分からないが、ブログ衰退の流れにあらがっていきたい。

| @ブログ

画像を拡大できるようにしたいという欲求は前々からあった。この手のものでは Lightbox が有名だが、 jQuery べったりなのでいまさら使いたくない。 P_BLOG の頃は FacyZoom というやつを使っていて好きだったが、 2008 年から更新されていない。何かいいのがないかなと探していて Medium Zoom というのを見つけた。

ブログサービスの Medium の画像拡大機能のコピープラグインだ。 npm パッケージになっているので導入も楽だった。

実際のこんな感じ。

Medium Zoom 利用風景
Medium Zoom 利用風景