PV(ページビュー)
サイトのページとCMSの記事に紐づく閲覧数を、genkoで確認するための設定と実装。
自分のサイトのページビューを計測し、genkoのワークスペースで確認できます。ページのパスだけでなく、CMSの記事に紐づく閲覧数を集計できるため、どの記事が読まれているかを確認できます。
管理画面では「メディア」の隣にある「PV」を開きます。コンテンツ一覧にも、文字数の下に記事ごとの閲覧数が表示されます。
受付ドメインを登録する
「PV」で計測を受け付けるドメインを登録します。登録・変更はオーナーまたはメンテナーが行います。登録できるのは最大20件で、サブドメインは別々に登録します。登録外のドメインからの閲覧と、localhostからの閲覧は計測しません。
レイアウトにPageViewを置く
Next.js App Routerでは@genko-me/react/nextからimportします。レイアウトに1つ置くと、各ページのパスを数えます。画面には何も描画しません。
import type { ReactNode } from "react";import { PageView } from "@genko-me/react/next";
export default function RootLayout({ children }: { children: ReactNode }) { return ( <html lang="ja"> <body> {children} <PageView workspace="your-workspace" /> </body> </html> );}workspaceにはワークスペースのスラッグを指定します。APIキーは不要です。最初の閲覧が届くと、管理画面は設定手順からグラフへ切り替わります。受信状況は10秒ごとに確認します。動作確認には登録済みドメインのサイトを使ってください。
記事ページでも数える
記事ページには、取得した記事のidを渡して追加します。これは記事の閲覧数だけを加算します。レイアウトで数えたパスを二重に数えることはありません。記事の閲覧数はワークスペース内の公開IDで集計するため、異なるAPIに同じIDの記事がある場合は同じ閲覧数を共有します。
import { PageView, ViewCount } from "@genko-me/react/next";
export function ArticleViews({ entry }: { entry: { id: string } }) { return ( <> <PageView workspace="your-workspace" entryId={entry.id} /> <ViewCount workspace="your-workspace" entryId={entry.id} /> </> );}Reactとルーター
Next.js以外のReactでは@genko-me/reactからimportします。pathを省略するとlocation.pathnameを使い、戻る・進むのpopstateに追従します。独自のルーターでは現在のパスをpathへ渡してください。値が変わるたびに送信します。
import { PageView } from "@genko-me/react";
export function SitePageViews({ pathname }: { pathname: string }) { return <PageView workspace="your-workspace" path={pathname} />;}Next.js版はusePathname()に追従するため、App Routerの画面遷移でも送信します。Vue・Svelte・Web Components用の部品は今後対応予定です。それまでは後述のJavaScript関数を使えます。
閲覧数を表示する
ViewCountは累計の表示専用で、閲覧数を加算しません。entryIdで記事、pathでページの累計を指定します。両方を渡すとentryIdが優先されます。
import { ViewCount } from "@genko-me/react";
export function ArticleCount({ entryId }: { entryId: string }) { return ( <ViewCount workspace="your-workspace" entryId={entryId} format={count => `${count.toLocaleString("ja-JP")} 回閲覧`} fallback={<span>—</span>} /> );}パス別なら<ViewCount workspace="your-workspace" path="/blog/hello" />を使います。累計は最大約5分キャッシュされるため、表示には少し遅れがあります。
| prop | 対象 | 使い方 |
|---|---|---|
workspace | 両方 | ワークスペースのスラッグ。React版では必須 |
baseUrl | 両方 | 省略時はhttps://api.genko.me |
entryId | 両方 | 記事の公開ID |
path | 両方 | PageViewでは省略時に現在のパス。ViewCountでは表示対象のパス |
format | ViewCount | 数値を受け取り、表示するReactNodeを返す関数 |
fallback | ViewCount | 取得前・取得失敗時の表示。省略時は何も表示しない |
locale | ViewCount | 桁区切りのロケール。既定はja-JP |
className | ViewCount | 表示するspanのCSSクラス |
Next.js版はサーバーコンポーネントから使い、workspaceの代わりにList・Viewと同じapi={client.blog}も指定できます。ブラウザにAPIキーは渡りません。Next.js版のViewCountはcacheで取得結果を再利用する秒数を指定でき、既定は300です。formatを使う場合もサーバー側で指定します。
JavaScriptや他のフレームワークで使う
ブラウザでページを表示したときにsendPageViewを呼びます。SPAではルーターの遷移後にも呼んでください。
import { sendPageView } from "@genko-me/core/browser";
sendPageView({ workspace: "your-workspace", path: location.pathname });// 記事ページでは記事の回数を別に加算します。sendPageView({ workspace: "your-workspace", entryId: "abcDEF123456" });累計の取得にはfetchViewCountsを使います。これはサーバー側でも使え、失敗時は例外を投げます。
import { fetchViewCounts } from "@genko-me/core";
const counts = await fetchViewCounts({ workspace: "your-workspace", entryIds: ["abcDEF123456"], paths: ["/blog/hello"],});console.log(counts.entries.abcDEF123456, counts.paths["/blog/hello"]);よく読まれている順に並べる
配信一覧のorders="-views"は累計閲覧数の多い順、orders="views"は少ない順です。未計測の記事は0として扱います。
import { List, ListItem } from "@genko-me/react/next";import { client } from "@/lib/client";
export default function PopularArticles() { return ( <List api={client.blog} orders="-views" limit={4} href="/blog/{id}"> <h2><ListItem id="title" /></h2> </List> );}SDKでもgenko.apis.blog.list({ orders: "-views", limit: 4 })を使えます。APIごとの累計と直近の集計は、認証付きのGET /v1/{workspace}/_views/{endpoint}?ids=a,b&days=30で取得できます。SDKではgenko.apis.blog.views({ ids: ["abcDEF123456"], days: 30 })を使います。低レベルクライアントにはclient.getViews(...)があります。詳しくはSDKリファレンスを参照してください。HTTPの入力・レスポンスは配信APIに記載しています。
計測と保存のルール
同じ端末から同じページへの閲覧は、30分に1回として数えます。IPアドレスとUser-Agentから日ごとに変わるソルト付きハッシュを作り、一時的な重複判定に使います。IPアドレスとUser-Agentそのものは保存しません。
保存する閲覧データは、ページのパスごと・記事ごとの日別回数だけです。パスのクエリとハッシュは取り除き、連続するスラッシュと末尾のスラッシュも正規化します。Cookieは使いません。リファラー・デバイス・国・訪問者の追跡情報も保存しません。
ボットや自動操作ブラウザ(navigator.webdriver)は計測せず、IPごとのレート制限もあります。送信はsendBeaconとtext/plainを使うためCORSプリフライトが不要で、利用できない場合はfetchへ切り替えます。送信の失敗はサイトの表示に影響しません。公開エンドポイントの仕様は配信APIを参照してください。
サイトのプライバシーポリシーには、ページのパスをgenko(genko.me)へ送信することを記載するとよい場合があります。
料金
計測は現在無料です。今後の無料枠と従量料金は未定です。
最終更新: 2026年10月19日