content scriptとは?Chrome拡張機能でWebページにボタンを追加する方法

公開日: 

以前の記事「Chrome拡張機能とは?できること・Webアプリとの違い」では、Chrome拡張機能がWebページ上の作業を補助できることを紹介しました。

popupは、ツールバーの拡張機能アイコンを押したときに開く小さな操作画面です。しかし、Chrome拡張機能らしい機能を作るには、popupだけでなく、現在開いているWebページ側へ処理を追加したい場面もあります。

たとえば、ページ上に独自のボタンを置く、表示中の文章を取得する、表の内容を読み取る、特定の項目を見つけやすくする、といった処理です。

このように、Webページの中で動くJavaScriptが content script です。

この記事では、初心者でも動きを確認しやすいように、https://example.com/* だけで動く小さな拡張機能を作ります。ページ右下に「PAGE INFO」ボタンを追加し、押すとページタイトルとURLを表示します。

content scriptがWebページに固定ボタンを追加する図解
content scriptがWebページに固定ボタンを追加する図解

content scriptとは

content scriptは、Chromeで開いているWebページの中で動くJavaScriptです。

通常のWebページでは、そのサイトが用意したHTML、CSS、JavaScriptが動いています。Chrome拡張機能では、設定した対象ページに対して、拡張機能側のJavaScriptやCSSを追加できます。

これにより、元のWebサイトを直接編集しなくても、利用者のブラウザ上で表示や操作を補助できます。

content scriptでできることの例は、次の通りです。

  • ページタイトルやURLを取得する
  • 見出し、本文、リンク、表などの要素を探す
  • ページ上に独自のボタンや情報パネルを追加する
  • 特定の項目へ色を付けて見つけやすくする
  • 入力フォームの補助をする
  • ページ上の情報を整理し、popupやbackground service workerへ渡す

たとえば、管理画面の決まった位置に確認ボタンを追加する、商品ページから必要な項目を抜き出す、YouTube Liveのコメント欄から情報を読み取る、といった処理はcontent scriptの領域です。

一方で、content scriptは何でも自由にできる場所ではありません。

どのページで動かすかを決め、必要な範囲だけに適用する必要があります。また、Webサイト側のHTML構造が変わると、要素を取得する処理が動かなくなる場合もあります。

まずは、対象を小さく限定したサンプルで基本を確認します。

今回作るもの

今回は、https://example.com/* を開いたときだけ動く拡張機能を作ります。

ページを開くと、右下に「PAGE INFO」という固定ボタンが表示されます。

ボタンを押すと、小さな情報パネルが開きます。パネルには、現在のページタイトルとURLを表示します。もう一度ボタンを押すと、情報パネルを閉じます。

今回の目的は、次の流れを理解することです。

  1. manifest.json で対象ページを指定する
  2. content.js をWebページ内で動かす
  3. JavaScriptでボタンと情報パネルを追加する
  4. content.css で見た目を整える
  5. Chromeで拡張機能を再読み込みし、対象ページで確認する

外部API通信、データ保存、popupとのメッセージ通信は扱いません。まずは、content scriptだけで完結する小さな機能を作ります。

ファイル構成

今回のフォルダ構成は次の通りです。

page-info-button-extension/
├─ manifest.json
├─ content.js
└─ content.css

役割は次の通りです。

ファイル役割
manifest.jsoncontent scriptを動かす対象ページとファイルを指定する
content.jsページ上にボタンと情報パネルを追加する
content.css追加したボタンと情報パネルの見た目を整える

popup画面は使いません。

今回は、ページを開いたときにcontent scriptが自動で読み込まれ、固定ボタンを追加する構成にします。

content script関連ファイルの関係図
content script関連ファイルの関係図

manifest.jsonでcontent scriptを登録する

まず、manifest.json を作ります。

{
  "manifest_version": 3,
  "name": "Page Info Button Extension",
  "version": "1.0.0",
  "description": "ページ上にタイトルとURLを確認するボタンを追加します。",
  "content_scripts": [
    {
      "matches": ["https://example.com/*"],
      "css": ["content.css"],
      "js": ["content.js"]
    }
  ]
}

今回の中心になるのは、content_scripts です。

content_scripts には、どのページへ、どのCSSとJavaScriptを追加するかを書きます。

"content_scripts": [
  {
    "matches": ["https://example.com/*"],
    "css": ["content.css"],
    "js": ["content.js"]
  }
]

matches は対象ページです。

css は対象ページへ追加するCSSファイルです。

js は対象ページで動かすJavaScriptファイルです。

このように manifest.json へ書いておく方法を静的登録と呼びます。対象ページを開くと、Chromeが指定したCSSとJavaScriptを読み込みます。

今回は run_at を指定していません。その場合、content scriptは既定の document_idle で挿入されます。初心者向けの小さなDOM操作では、まず既定値のまま試すと理解しやすいです。

matchesで対象ページを限定する

matches は、content scriptを動かすページを決める重要な設定です。

今回の指定は次の通りです。

"matches": ["https://example.com/*"]

これは、HTTPSで開いた example.com 配下のページを対象にする指定です。

末尾の * は、パス部分をまとめて対象にするためのワイルドカードです。

たとえば、次のように広い指定を書くと、多くのHTTPSページでcontent scriptが動きます。

"matches": ["https://*/*"]

広い指定は便利に見えますが、意図しないサイトでも処理が動きます。公開する拡張機能では、利用者に対してアクセス範囲を説明する必要もあります。

まずは、必要なサイトだけに限定します。特定の管理画面だけで使うなら、そのドメインだけを対象にします。

content.jsでボタンと情報パネルを追加する

次に、content.js を作ります。

const BUTTON_ID = "page-info-extension-button";
const PANEL_ID = "page-info-extension-panel";

if (!document.getElementById(BUTTON_ID)) {
  const button = document.createElement("button");
  button.id = BUTTON_ID;
  button.type = "button";
  button.textContent = "PAGE INFO";

  const panel = document.createElement("section");
  panel.id = PANEL_ID;
  panel.hidden = true;

  const titleLabel = document.createElement("strong");
  titleLabel.textContent = "TITLE";

  const titleText = document.createElement("p");
  titleText.textContent = document.title || "タイトルなし";

  const urlLabel = document.createElement("strong");
  urlLabel.textContent = "URL";

  const urlText = document.createElement("p");
  urlText.textContent = location.href;

  panel.append(titleLabel, titleText, urlLabel, urlText);

  button.addEventListener("click", () => {
    panel.hidden = !panel.hidden;
  });

  document.body.append(button, panel);
}

最初に、追加する要素のIDを定数として用意しています。

const BUTTON_ID = "page-info-extension-button";
const PANEL_ID = "page-info-extension-panel";
if (!document.getElementById(BUTTON_ID)) {

これは重複挿入を防ぐガードです。処理が再実行されても、ボタンを複数追加しません。

次に、document.createElement() でボタンを作ります。

const button = document.createElement("button");
button.id = BUTTON_ID;
button.type = "button";
button.textContent = "PAGE INFO";

情報パネルも同じように作ります。

ページタイトルは document.title から取得します。

URLは location.href から取得します。

titleText.textContent = document.title || "タイトルなし";
urlText.textContent = location.href;

ボタンが押されたときは、hidden の値を切り替えます。

button.addEventListener("click", () => {
  panel.hidden = !panel.hidden;
});

最後に、作った要素を document.body へ追加します。

document.body.append(button, panel);

これで、対象ページの右下に表示するための要素が追加されます。

ボタン操作でページ情報パネルが表示される図解
ボタン操作でページ情報パネルが表示される図解

content.cssで見た目を整える

次に、content.css を作ります。

#page-info-extension-button {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 2147483647;
  border: 0;
  border-radius: 8px;
  padding: 10px 14px;
  color: #ffffff;
  background: #2563eb;
  font: 700 13px/1.4 system-ui, sans-serif;
  cursor: pointer;
  box-shadow: 0 6px 18px rgba(15, 23, 42, 0.2);
}

#page-info-extension-panel {
  position: fixed;
  right: 20px;
  bottom: 72px;
  z-index: 2147483647;
  width: 280px;
  border: 1px solid #bfdbfe;
  border-radius: 10px;
  padding: 14px;
  color: #1f2937;
  background: #ffffff;
  font: 14px/1.6 system-ui, sans-serif;
  box-shadow: 0 12px 28px rgba(15, 23, 42, 0.18);
}

#page-info-extension-panel p {
  margin: 4px 0 12px;
  overflow-wrap: anywhere;
}

ボタンと情報パネルには、記事専用のIDを使っています。

Webページ側にもさまざまなCSSがあります。一般的なクラス名だけを使うと、既存ページのCSSと衝突する可能性があります。

そのため、拡張機能が追加した要素だと分かる名前を付けています。

position: fixed を使うことで、ページをスクロールしても右下へ固定されます。

Chromeで動作確認する

3つのファイルを作ったら、Chromeで拡張機能を読み込みます。

手順は次の通りです。

  1. Chromeで chrome://extensions を開く
  2. 右上のデベロッパーモードをオンにする
  3. 「パッケージ化されていない拡張機能を読み込む」を押す
  4. page-info-button-extension フォルダを選ぶ
  5. https://example.com/ を開く
  6. ページ右下に「PAGE INFO」ボタンが表示されることを確認する
  7. ボタンを押し、タイトルとURLが表示されることを確認する

ファイルを変更した場合は、拡張機能管理画面で再読み込みボタンを押します。

ここで注意したいのは、拡張機能だけでなく、対象のWebページも再読み込みすることです。

content scriptは、対象ページを開いたときや再読み込みしたときに挿入されます。content.js を修正したあと、Webページを開いたままにしていると、古い処理が残っているように見える場合があります。

content scriptを作るときの注意点

content scriptは便利ですが、対象ページの中で動くため、いくつか注意点があります。

動かないページがある

今回の設定では、https://example.com/* だけで動きます。

別のサイトを開いてもボタンは表示されません。

また、Chromeの設定画面や拡張機能管理画面など、chrome:// から始まるページでは通常のWebページと同じようにcontent scriptを動かせません。

対象ページで動かない場合は、まずURLと matches が一致しているかを確認します。

matchesを広げすぎない

すべてのサイトで動かす必要がないなら、対象を限定します。

公開する拡張機能では、なぜそのサイトへアクセスする必要があるのかを説明できる状態にしておくことが大切です。

既存ページへの影響を小さくする

既存ページの要素を直接書き換える場合は、より慎重に扱います。

たとえば、一般的な button 要素すべてにCSSを当てると、元のWebサイトのボタンまで変わる可能性があります。拡張機能が追加した要素だけを対象にします。

DOM構造の変更を考慮する

特定の要素を探す処理を書く場合は、対象が見つからないケースを考えます。

const target = document.querySelector(".target-item");

if (!target) {
  console.warn("対象要素が見つかりませんでした");
  return;
}

外部サイトに依存する拡張機能では、サイト側の変更に合わせて保守する必要があります。

外部入力は安全に扱う

ページから取得した文字列を表示するときは、textContent を使うと安全に扱いやすくなります。

取得した文字列をそのまま innerHTML へ入れると、意図しないHTMLとして解釈される可能性があります。

今回のサンプルでも、タイトルとURLは textContent で設定しています。

静的登録と動的挿入の違い

この記事では、manifest.jsoncontent_scripts に書く静的登録を使いました。

対象ページを開いたときに、自動で content.jscontent.css が適用されます。

一方で、ユーザーが操作したときだけ追加したい場合は、activeTab 権限や chrome.scripting.executeScript() を使った動的挿入を検討します。

方法向いている用途
静的登録対象ページを開いたとき、毎回必要な補助機能を表示する
動的挿入ユーザーが操作したときだけ、一時的に処理を実行する

今回はcontent scriptの基本を理解するため、静的登録に集中しました。動的挿入やpopupとの連携は、後続の記事で扱います。

今回のサンプルで分かること

今回の拡張機能では、content scriptの基本的な流れを確認できました。

  • content_scripts で対象ページへCSSとJavaScriptを追加できる
  • matches で対象サイトを限定できる
  • document.createElement() でページ上に要素を追加できる
  • textContent で文字列を安全に表示しやすくなる
  • addEventListener() でボタン操作に反応できる
  • IDを確認して重複挿入を防げる
  • 拡張機能を変更した後は、対象ページも再読み込みする

次の記事では、chrome.storage を使って設定値を保存する方法を扱います。たとえば、機能をONにするか、どの表示方法を使うか、といった設定をブラウザ内へ保存できるようになります。

参考リンク

まとめ

この記事では、Chrome拡張機能のcontent scriptを使い、Webページ上へ固定ボタンと情報パネルを追加しました。

content scriptは、開いているWebページの中で動くJavaScriptです。

manifest.jsoncontent_scriptsmatchescssjs を書くと、対象ページへ拡張機能側の処理を追加できます。

今回のサンプルでは、https://example.com/* だけを対象にしました。

対象を必要な範囲に限定し、追加した要素には固有のIDを付け、表示する文字列は textContent で設定しました。

Chrome拡張機能で業務効率化ツールを作るとき、Webページに関わる処理はcontent scriptが担当することが多くなります。

まずは小さなボタン追加から始め、動作確認の手順と注意点を押さえておくと、情報取得、入力補助、保存処理へ安全に広げやすくなります。




Your Message

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

スポンサードリンク

記事が気に入ったらシェアお願いします

PAGE TOP ↑