0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

検索条件をURLに同期するとUTMが消える。閲覧用URLと共有用URLを分けて直す

0
Last updated at Posted at 2026-10-10
1分でわかる要点
  • 検索条件だけでURLを組み直すと、来訪元の目印であるUTMが消えます。
  • 閲覧用URLは許可したUTMとhashを保持し、共有用URLは検索条件だけにします。
  • 既存クエリを丸ごと残さず、allowlistで引き継ぐキーを決めます。

JavaScriptで検索条件をURLへ同期すると、検索語は反映されても、訪問時に付いていたUTMが消えることがあります。個人開発での修正をもとに、閲覧用URLと共有用URLを分ける方法を説明します。

UTMは「どこから来たか」を示すURLの目印

たとえば、メールに置くリンクに次の目印を付けます。

https://example.com/search?utm_source=newsletter&utm_medium=email&utm_campaign=autumn

utm_sourceは参照元、utm_mediumは媒体、utm_campaignはキャンペーンを区別します。この記事では、これらにutm_term、utm_content、utm_idを加えた6項目を保持します。UTM全種類の一覧ではありません。Google公式のUTMの説明

UTMの保持と計測の成功は別で、GA4の実データ集計や認証接続の成功は確認していません。

同意前の検索で消える経路

計測タグを同意後に読み込む画面では、次の順序でUTMを失うことがあります。

  1. UTM付きリンクから訪問する。
  2. 同意する前に検索する。
  3. 検索条件だけでURLを再構築する。
  4. 後から同意しても、その時点のURLにUTMがない。

検索語qだけから?q=webを作ると、元のUTMは自動では引き継がれません。URLSearchParamsが消したのではなく、新しいURLへ含めなかったためです。同意の条件は変えず、URL更新時に必要な情報を残します。

閲覧用と共有用で、残す情報を決める

図はURLの保持方針を示しています。計測データの送信経路ではありません。

  • 閲覧用: 最新の検索条件に、許可したUTMとhashを追加する。
  • 共有用: 検索結果の再現に必要な、最新の検索条件だけを使う。

既存クエリを丸ごとコピーせず、引き継ぐキーをallowlist(許可リスト)で決め、未知キーは除外します。元の訪問者のUTMを共有先へ持ち越さないための区別です。ただし、アドレス欄を直接コピーした場合はUTMも含まれます。

URLを作る処理を、画面の更新から分ける

以下は説明用に一般化したコードです。検索条件を文字列qに絞り、現在地はHTTP(S)のURLオブジェクトで受け取ります。

const UTM_KEYS = [
  "utm_source", "utm_medium", "utm_campaign",
  "utm_term", "utm_content", "utm_id",
];

/**
 * @param {string} q 検索語
 * @returns {URLSearchParams} 検索条件だけ
 */
function searchParams(q) {
  const params = new URLSearchParams();
  if (q.trim()) params.set("q", q.trim());
  return params;
}

/**
 * @param {URL} current 現在のURL
 * @param {string} q 検索語
 * @returns {string} 閲覧用の同一オリジンURL */
function browsingURL(current, q) {
  const params = searchParams(q);
  for (const key of UTM_KEYS) {
    if (current.searchParams.has(key)) {
      params.set(key, current.searchParams.get(key));
    }
  }
  const query = params.toString();
  return current.origin + current.pathname
    + (query ? "?" + query : "") + current.hash;
}

/**
 * @param {URL} current 現在のURL
 * @param {string} q 検索語
 * @returns {string} UTMとhashを含まない共有用URL */
function sharingURL(current, q) {
  const query = searchParams(q).toString();
  return current.origin + current.pathname + (query ? "?" + query : "");
}

browsingURLだけがUTMとhashを引き継ぎ、sharingURLは検索条件だけから作ります。検索語を空にすればqだけが消え、閲覧用のUTMとhashは残ります。

UTMが重複した場合はget()で最初の値を取得し、set()で1つにします。空値はそのまま保持します。MDN: get()

日本語や&、+は値としてset()へ渡せば、toString()が変換します。先にencodeURIComponentをかける必要はありません。MDN: URLSearchParams

画面側では、入力から読んだ検索語qを渡します。

const current = new URL(location.href);
history.replaceState(history.state, "", browsingURL(current, q));
// 共有ボタンでは sharingURL(new URL(location.href), q) を使う。

replaceStateはページを再読み込みせず、現在の履歴エントリーを更新します。URLは同一オリジンに限定し、ルーターを使う場合はその更新APIに合わせてください。MDN: replaceState()

まとめ

URLを同期するときは、閲覧用と共有用で残す値を分けます。閲覧中のURLでは許可したUTMとhashを保持し、共有URLは検索条件だけから作ることで、元の流入元情報を共有先へ持ち越さずに済みます。

AIが本文整理と説明用コードの作成・実行確認を補助しました。題材・公開範囲・計測成功を主張しない方針は本人の指定に基づきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?