WordPressのサイトを何年か運用していると、「あのページ、まだ去年の情報のままだった」という事故が必ず起きます。誰が見直すのか、いつまでに見直すのかが決まっていない。決まっていても、覚えているのは人の頭の中だけ。この記事は、その「誰が・いつまでに・どこを」をWordPressの中に持たせる方法の全体像で、コンテンツ更新管理というプラグインを作った側からの説明でもあります。
このプラグインを作り始めたとき、最初に捨てたのが「公開期限」という言葉でした。公開期限は、日付が来たら投稿の状態を変える仕組みです。キャンペーンページを終了日に非公開にする、といった用途には十分で、そういうプラグインはすでにあります。でも企業サイトやオウンドメディアで実際に困っているのは、期限が来て消したいページではなく、期限が来ても誰も見ていないページのほうでした。料金表が去年のまま、営業時間が移転前のまま、注意書きが法改正前のまま。消すべきではないが、誰かが確認して「まだ合っている」か「直した」かを言わないといけない。
だから設計の軸を「公開期限」ではなく「次回確認日」にしました。日付が来たら状態を変えるのではなく、日付が来たら人に確認させ、確認が終わったら次の日付を作る。この記事では、その考え方でWordPressの中に更新管理を置くとどうなるかを、コンテンツ更新管理というプラグインの実装に沿って一通り書きます。
誰が・いつまでに・どこを、の「どこを」が記事単位では粗い

更新期限を管理しようとして最初にぶつかるのは、単位の問題です。
「この記事を3か月ごとに見直す」と決めても、記事の中には鮮度の違う情報が同居しています。料金表は四半期ごとに変わるのに、会社沿革は何年も変わらない。記事単位で期限を切ると、変わらない部分のために毎回全体を読み直すか、変わる部分の期限を全体に引きずられて見逃すかのどちらかになる。
コンテンツ更新管理では管理する単位を4つ用意しました。
| 単位 | 何を管理対象にするか | 1記事あたり |
|---|---|---|
| 投稿 | 投稿・固定ページ・カスタム投稿タイプの1件そのもの | 1つ |
| 管理ブロック | 本文の中で「コンテンツ更新管理セクション」ブロックで囲んだ範囲 | 何個でも |
| ACFフィールド | Advanced Custom Fields で定義したフィールドの値 | 何個でも |
| カスタムフィールド | 任意の投稿メタの値 | 何個でも |
1つの記事の中で「料金表のブロックは3か月ごと、注意事項のブロックは毎年、記事全体は2年ごと」のように分けられます。それぞれが独立した管理対象で、担当者も期限も別に持てる。ここがこの製品の中心で、記事の一部分だけを管理する話は別に詳しく書きました。
投稿そのものの管理対象は1記事に1つだけです。ブロックとフィールドは何個でも。ACFが入っていないサイトではACFの項目が出ないだけで、他の3つは使えます。
管理対象ごとに持たせるもの
どの単位でも、管理対象には同じ情報を持たせます。担当者、承認者、エスカレーション先、次回確認日、更新頻度、重要度、確認メモ、参照URL、通知の設定、期限切れ時の処理。
このうち必須なのは管理対象名・担当者・次回確認日・重要度・期限切れ処理の5つで、承認者とエスカレーション先は任意です。担当者にはその投稿を編集できるユーザーだけを選べるようにしてあります。確認作業の画面には本文やフィールドの値がそのまま出るので、編集権限の無い人を担当者にすると「担当なのに開けない」という状態ができるからです。担当者と承認者の兼任もできません。自分で確認して自分で承認する承認は、承認ではないからです。
更新頻度は「1〜999」と「日・週・月・年」の組み合わせで、確認が完了すると完了日と頻度から次回確認日を自動で計算します。1月31日の1か月後は2月28日(か29日)に丸める、という月末の扱いも入れてあります。頻度を「なし」にすれば日付は動きません。一度きりの確認、たとえば「来年の法改正が施行されたら見直す」のような使い方はこちらです。
期限が来る前に知らせる、来ても知らせる

期限の状態は、次回確認日を基準に「期限前」「期限接近」「期限当日」「期限超過」の4つを自動で判定します。期限接近の閾値は既定で7日前、1〜90日の範囲で変えられます。
通知は期限前・期限当日・期限超過・エスカレーション(超過が続いたときに上長へ)・承認依頼・承認・差し戻し・期限切れ処理の実行、の8種類。送り先はメール、Slack、Chatworkの3チャンネルです。期限前と期限超過は「14日前・7日前・1日前」のように日数を複数指定できるので、1回見逃しても次が来る。同じ通知が二重に飛ばないよう、確認サイクル・イベント・チャンネル・宛先の単位で重複を防いでいます。
届かなかった通知は「通知ログ」に理由つきで残り、毎時の定期処理で自動的に再送します。ここは実際に運用が始まると気になるところで、通知の設定と届かないときの追い方は別記事にまとめました。
期限を過ぎたときに何をするか(何をしないか)
期限切れ時の処理は管理単位ごとに選べます。
- 投稿:管理画面で警告のみ/下書きへ戻す/非公開にする/指定URLへリダイレクト(301・302)
- 管理ブロック:警告のみ/フロントで非表示/代替メッセージに差し替え
- ACF・カスタムフィールド:警告のみ/通知のみ
決めていたのは、どの処理も本文やフィールドの値を書き換えないこと。期限が来たからといって料金表を消したり、フィールドを空にしたりはしません。ブロックの非表示も代替メッセージも表示のたびに差し替えているだけで、保存された本文はそのままです。確認が完了すれば非表示・代替メッセージ・リダイレクトは自動で解除されます。下書き・非公開にした投稿だけは自動では戻さず、「以前の公開状態へ戻す」を人が押します。勝手に公開されると困る場面のほうが多いと考えたからです。
既定は「何もしない」です。導入した日に何かが非公開になることはありません。期限切れ処理の選び方と戻し方は、それだけで1本の記事になりました。
確認したことを、確認したと言えるようにする
確認は「未対応 → 確認中/修正中 → 承認待ち → 完了」と進みます。完了には「更新あり」「変更なし」「対象外」の3種類があり、「見たけど変えていない」も記録に残る。承認者を置いている管理対象は承認されるまで完了にならず、差し戻すには理由が要ります。承認待ちの間に中身が変わったら承認は無効になって「修正中」へ戻ります。承認した内容と公開されている内容が違う、を防ぐためです。
この流れは投稿でもブロックでもフィールドでも同じで、承認の流れと権限の分け方は別に書いています。
履歴には誰が・いつ・何をしたかが管理対象ごとに残ります。担当者や次回確認日を変えたときは変更前と変更後の値まで、通知は宛先と役割(担当者宛か承認者宛か)まで。「確認済みです」を口頭ではなく画面で示せる状態にしておくと、監査や引き継ぎで効きます。
一覧で見る、自分の分だけ見る

管理対象が増えると、個別の投稿を開いて回るのは無理。管理画面には管理対象の一覧(絞り込み・並び替え・一括操作)、自分が担当している分だけを集めた画面、期限や重要度の状況をまとめたダッシュボードがあります。
一覧に何が出るかは権限で変わります。管理対象全体を管理できる人(既定では管理者・編集者)は全件、それ以外の人には自分が担当者・承認者・エスカレーション先になっている行と、自分が作成した投稿の行だけ。同じ画面を開いても人によって件数が違うので、最初は戸惑うかもしれません。
権限は「確認を実行」「承認を実行」「管理対象を編集」「管理対象全体を管理」「設定を変更」の5つに分けてあり、既定では管理者に全部、編集者に確認・承認・編集、投稿者に確認・編集を割り当てています。権限を持たない人には管理画面もメタボックスも出ません。
投稿ごとに設定して回らなくていい
100本の記事に1本ずつ担当者と頻度を入れて回るのは現実的ではありません。「この投稿タイプ・このカテゴリなら、担当者は誰・更新頻度は何か月・通知はどうする」を運用ルールとして登録しておくと、条件に一致した新規投稿へ自動で適用され、既存の投稿へもまとめて適用できます。
動かすために必要なもの
WordPress 6.6以上、PHP 8.1以上。定期処理はWP-Cronで毎時走るので、DISABLE_WP_CRON でコアのcronを止めているサイトはサーバーのcronから wp cron event run --due-now を回す必要があります。Slackへの通知はIncoming WebhookのURL、ChatworkはAPIトークンとルームIDが要ります。通知はメールだけでも動きます。
作っている側から言っておくと、このプラグインは古くなった情報を自動で見つけてはくれません。期限を決めるのも、確認するのも人です。プラグインがやるのは、決めた期限を忘れさせないことと、確認したという事実を残すこと。それで十分だと思って作りました。
製品ページは コンテンツ更新管理 にあります。
