アクセスカウンターと拍手の実装

日付
閲覧数
拍手

個人サイトといえばやはりアクセスカウンターとWeb拍手、これらは承認欲求たすための二大要素です。 従前であればCGIを使って実装していたといますが、さいきんなのでCloudflare D1で実装しました。 実装はぜんぶClaude Codeにおまかせなので、こういうかんじでっていう設計しかしていません。以下説明Claude Codeいてもらったのでそういうことでよろしくおねがいします。

このサイトharukasan.devはCloudflare Pages構成されておりHonoX使ってつくられています。 サイト本体はSSGしていますが、Pages前段にはWorkerがいるので、動的なエンドポイントだけはWorkerかすことができます。

island数字

記事のHTMLはSSGされた静的ファイルなので、数字はビルドした時点固定されてしまいます。そこで数字部分だけをHonoXislandにして、ページをいたあとにブラウザからりにいきます。日付閲覧数拍手数記事末尾拍手ボタンがそれぞれislandです。取得できるまではかないので、数字があとからてきてもレイアウトはきません。

かぞえかた

閲覧数はのべ日次ユニーク訪問者数です。記事何度リロードしても、そのは1しかえません。翌日になるとまた1えます。「」は日次ハッシュでています。秘密日付・IPアドレス・User-Agentのハッシュで、日付っているのでをまたぐとになります。

テーブルは3つです。

-- 記事ごとの累計
CREATE TABLE page_counts (
  path TEXT PRIMARY KEY,
  count INTEGER NOT NULL DEFAULT 0,
  claps INTEGER NOT NULL DEFAULT 0
) WITHOUT ROWID;

-- 閲覧数の重複排除用。visitor は日次ハッシュ
CREATE TABLE page_count_visitors (
  path TEXT NOT NULL,
  visitor TEXT NOT NULL,
  created_at INTEGER NOT NULL DEFAULT (unixepoch()),
  PRIMARY KEY (path, visitor)
) WITHOUT ROWID;

-- 拍手の日次上限用。claps はその訪問者の今日の回数
CREATE TABLE page_clap_visitors (
  path TEXT NOT NULL,
  visitor TEXT NOT NULL,
  claps INTEGER NOT NULL DEFAULT 0,
  created_at INTEGER NOT NULL DEFAULT (unixepoch()),
  PRIMARY KEY (path, visitor)
) WITHOUT ROWID;

累計page_countsっているので、表示のたびにえなおすことはありません。日次ハッシュの2日します。

加算はページをいたときにブラウザからるPOSTの処理でおこないます。SQLはこの2です。

INSERT INTO page_counts (path, count) VALUES (:path,
  1 - coalesce((SELECT 1 FROM page_count_visitors
                WHERE path = :path AND visitor = :visitor), 0))
ON CONFLICT (path) DO UPDATE SET count = count +
  (1 - coalesce((SELECT 1 FROM page_count_visitors
                 WHERE path = :path AND visitor = :visitor), 0));

INSERT OR IGNORE INTO page_count_visitors (path, visitor)
  VALUES (:path, :visitor);

その訪問者をそのまだ記録していなければ1、記録済みなら0になるしこみます。えるをSQLのなかでめるのがポイントで、アプリがんでからくと、途中失敗したときに訪問者記録だけって二度えられなくなります。2は1トランザクションで実行します。

拍手は1が1記事につき110までです。連打されるので1クリックごとにはらず、クリックがまって1たったらまとめてります。るのは差分ではなく「今日この記事拍手した累計」で、えるはこうめます。

max(:total - coalesce((SELECT claps FROM page_clap_visitors
                       WHERE path = :path AND visitor = :visitor), 0), 0)

数字何度いても2回目からは0です。送信なってもタブが複数あっても二重になりません。

というわけで、ここまでんでいただいたはぜひ拍手ボタンをしていってください。110までせます。

0 / 10