> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kameleoon.com/llms.txt
> Use this file to discover all available pages before exploring further.

# シングルページアプリでの実験のセットアップ（React、Next.js、Vue.js...）

> Kameleoon を構成して、SPA サポートを有効にし、動的なページ変更を処理することで、シングルページアプリケーションで実験を実行します。

## シングルページアプリ（SPA）とは

### 定義と目的

シングルページアプリケーション（SPA）は、ページ全体を再ロードすることなくコンテンツを動的に更新することで、よりスムーズで高速なユーザー体験を提供するように設計されたウェブアプリケーションの一種です。SPA は通常、React、Next.js、Vue.js などのモダンな JavaScript フレームワークを使用して構築されます。多くの SPA はサーバーサイドレンダリング（SSR）も利用しており、これにより A/B テストやパーソナライズなどのクライアントサイド実装の複雑さが増します。

SPA の主な利点は、リソースを 1 回ロードしてコンテンツを動的に更新することで、各アクションの後にページ全体を再ロードするのではなく、訪問者のナビゲーション体験を改善することです。

### 実装の課題と解決策

SPA は、バリエーションを適用したりスクリプトを実行するためにページロードに依存する Kameleoon のようなツールに独自の課題をもたらします。最適なパフォーマンスを確保するためには、扱う SPA のタイプに基づいて実装戦略を調整することが重要です。

以降のセクションでは、各シナリオを処理するためのベストプラクティスと手順を概説し、ウェブサイト全体でスムーズな統合と訪問者行動の正確な追跡を実現します。

## ネイティブセットアップ

ウェブサイトがフルサイト SPA の場合、**「support for dynamic websites」** オプションを有効にすると、Kameleoon が URL の変更を監視するようになります。URL が変更されると、ターゲティングコードやバリエーションコードを含むすべての Kameleoon スクリプトが再実行されます。

Kameleoon はまた、**`MutationObserver`** を使用して DOM の変更を追跡することで、ページ URL が静的なままであっても SPA の更新を監視します。これにより、Kameleoon はウェブサイトで更新が発生したときに、バリエーション変更を動的に適用（または再適用）できます。Kameleoon は、グラフィックエディタを通じて行われたさまざまな変更をサポートします。

* スタイル変更
* テキストの変更
* 位置の更新（入れ替え、前後への挿入）
* カスタム CSS セレクタ

このアプローチにより、動的な環境でもすべての関連する変更が一貫して適用されます。

**動的ウェブサイトのサポート** を有効にするには:

1. **Admin** > **Projects** をクリックします。
2. プロジェクトのカードを見つけ、**Edit** アイコンをクリックします。
3. **Configuration** をクリックし、**General** メニューを展開します。
4. **Advanced settings** までスクロールし、**Enable support for dynamic websites (Single Page App, Progressive Web App...)** を **ON** にします。

<Frame>
  ![](https://storage.googleapis.com/kameleoon-storage-documentation/user-manual/images/experimentation/web-experimentation/advanced-experiment-types/set-up-an-experiment-on-a-single-page-app/advanced-settings.png)
</Frame>

構成を最適化するためのいくつかのオプションが利用できます。

* **スコープの選択:** サイト全体に対して機能を有効にするか、Graphic エディタを使用して特定の要素に制限できます。スコープを選択した要素に制限すると、全体的なスクリプトの重さを減らすのに役立ちます。要素を動的としてマークする方法については、[こちら](../graphic-based-experiments/edit-a-variation#動的要素を有効にする) を参照してください。

* **カスタム属性の設定（オプション）:** このオプションは要素の識別を改善し、動的な属性とセレクタに関連する問題を回避するのに役立ちます。ウェブサイトが安定または一意の HTML ID を生成しない場合、Kameleoon が変更された要素を識別する際に使用するカスタム属性を定義できます。この属性は、セレクタを構築する際に要素 ID よりも優先されます。

* **動的 ID セレクタの回避（オプション）:** このオプションも、動的な属性とセレクタを扱う際に要素の識別を改善します。デフォルトでは、Kameleoon は 5 桁を超える数字シーケンスを含む HTML ID を無視します。必要に応じて、追加の ID パターンを除外する独自の正規表現を定義できます。

### カスタム属性の設定

ページ上の要素を識別するためのカスタム属性（例: `data-id`、`data-qa`）を定義できます。カスタム属性は、サイトが HTML 要素に対して動的 ID を生成する場合に特に役立ちます。

Kameleoon Graphic エディタは、**CSS セレクタ** を使用して要素を識別します。これは 2 つのカテゴリに分類されます。

* **ID ベースの選択:** 要素に ID がある場合、Kameleoon はそれを使用してページがロードされたときに要素を特定し変更します。
* **コンビネータセレクタ:** ID が見つからない場合、Kameleoon は ID を持つ最も近い親要素を使用してセレクタパスを作成します。

ID が動的で頻繁に変更される場合、Graphic エディタは要素の識別に苦労する可能性があります。この問題を解決するには、更新全体で要素を確実に識別する静的なカスタム属性（例: `<button custom-id="1">`）を追加できます。

### 動的 ID セレクタの回避

デフォルトでは、Kameleoon は 5 文字を超える動的に生成された数字を含む要素 ID の使用を避けます。代わりに、ID を持つ近くの静的な親要素を使用してパスを構築します。

**正規表現** を指定して特定の動的 ID を除外することで、この動作をカスタマイズし、より正確なターゲティングを実現できます。

## カスタムセットアップ

ウェブサイトがフルサイト SPA でない場合や、サイトの特定の部分を処理する必要がある場合は、以下のセクションを参照してください。

カスタム SPA セットアップには、4 つの異なるユースケースがあります。

### 部分サイト SPA

特定のページに対してこのオプションを有効にするには、**Advanced settings** から無効にし、**Global script** に次のコードを追加します。

```javascript theme={null}
if (document.location.href.includes('mySPApage')) {
     Kameleoon.API.Core.enableSinglePageSupport();
 }
```

*「mySPApage」をファネルの URL に置き換えます。*

### URL の変更なしのページ変更

DOM が URL を変更せずに更新される場合は、Kameleoon を再ロードするための代替インジケーターに頼ります。以下は、`sessionStorage` を使用してページの変更を検出する例です。コードを **Global script** に追加できます。

```javascript theme={null}
window.kam_step = JSON.parse(window.sessionStorage.getItem('formStep'))?.step;
 Kameleoon.API.Core.runWhenConditionTrue(() => {
     return window.kam_step != JSON.parse(window.sessionStorage.getItem('formStep'))?.step;
 }, () => {
     Kameleoon.API.Core.load();
 });
```

### `pathname` でページの変更を検出する

Kameleoon を再実行する必要があるが、**`pathname`** が変更されたときのみ（クエリパラメータを無視する）必要があるページの場合、完全な URL の代わりに `pathname` を使用して変更を検出します。以下のコードを **Global script** に追加できます。

```javascript theme={null}
if (document.location.href.includes('configurator')) {
     window.kam_configurator_url = document.location.pathname;
 `Kameleoon.API.Core.runWhenConditionTrue(() => {     return window.kam_configurator_url != document.location.pathname; }, () => {     Kameleoon.Gatherer.Referrer.update(window.kam_configurator_url);     Kameleoon.API.Core.load(); });`
 } else {
     Kameleoon.API.Core.enableSinglePageSupport();
 }
```

### Kameleoon を再ロードせずにバリエーションコードを再適用する

場合によっては、特定のページ要素が動的で、コードが再ハイドレートされると、すでに適用されている Kameleoon コードが上書きされる可能性があります。これを防ぐには、2 つのオプションがあります。

* 次のいずれかの方法を使用して、ページまたは特定の要素のレンダリングが完了したことを Kameleoon に通知できます。
  * window 変数を定義します。例: `window.pageLoadForKam = true`。
  * Kameleoon がリッスンできるイベントをページでトリガーします。たとえば、`pageLoaded` または `contentUpdated` を使用します: `window.addEventListener('pageLoaded', () -> { runKameleoonVariationCode })`。
  * `<body>` タグまたはターゲット要素に特定のクラスまたは属性を追加します。次に、**バリエーションコード** でこのクラスまたは属性を使用して、ページや特定の要素に変更を加えます。
* **バリエーションコード** で、`runWhenElementPresent` 関数の 4 番目の引数を `true` に設定できます。この引数により、動的要素とシングルページアプリケーション（SPA）のサポートが有効になります。このオプションが有効な場合、Kameleoon が初期ページロード中に要素の指定された CSS セレクタを見つけられないと、Kameleoon は DOM でセレクタを監視します。要素が DOM に表示されると、Kameleoon はコールバック関数を実行します。さらに、セレクタに一致する新しい要素が後でページに追加された場合、Kameleoon は新たに追加された要素でコールバックを再実行します。

<Warning>
  以下のコードは控えめに、絶対に必要な場合にのみ使用してください。使用を最小限のケースに制限し、複数の要素に同時に適用することを避けて、最適なページパフォーマンスを維持してください。ページのソースコードが要素を更新するたびに変更する場合、**無限ループ** の可能性があることに注意してください。
</Warning>

```javascript theme={null}
const insertMyNewCTA = () => {
     if (document.querySelector("#kameleoonElement-myNewCTA") == null) {
 `    Kameleoon.API.Core.runWhenElementPresent(         '#myElement',         ([myElement]) => {             myElement.insertAdjacentHTML('beforebegin', "<button id='kameleoonElement-myNewCTA'>More info</button>");         },         null, true     ); }`
 }
 insertMyNewCTA();
```

### dataLayer からデータを取得する

カスタムデータ値を設定するための取得方法として GTM を使用する場合、Kameleoon は定義された `dataLayer` に依存して値にアクセスします。各 URL 変更後に古いエントリを削除する代わりに新しいエントリを積み重ねることで `dataLayer` が更新されている場合、Kameleoon は古い値を取得する可能性があります。この取得は、古いデータがページ間で残るためで、Kameleoon は `dataLayer` が更新される前に実行する可能性があります。この問題を防ぐには、新しいエントリを追加する前に古いエントリが削除されていることを確認してください。または、最新の値を取得する前に `dataLayer` の長さの変更を待つカスタムコードを実装してください。

```javascript theme={null}
`window.dataLayerLength = window.dataLayerLength || 0; Kameleoon.API.Core.runWhenConditionTrue(() => { return window.dataLayer && window.dataLayerLength != window.dataLayer.length }, () => { window.dataLayerLength = window.dataLayer.length //then, retrieve and use dataLayer info here })`
```

## 一般的な考慮事項

### イベントリスナー、タイムアウト、インターバル

イベントリスナー、タイムアウト、またはインターバルを管理するには、`Kameleoon.API.Utils` を使用します。これらのメソッドにより、ページのリロードなしに URL の変更が発生したときに、リスナーとタイマーが自動的に削除されます。これらの削除により、Kameleoon が再実行されたときの重複を防ぎます。

### 一意の要素 ID

Kameleoon を介して要素を追加する場合、その `id` が `kameleoonElement` で始まることを確認してください。この命名規則により、Kameleoon が再実行される前に要素が削除されることが保証され、重複や衝突を回避できます。

**例:**

`<div id="kameleoonElement-myNewCTA"></div>`

### ページビューの増分

Kameleoon は、すべてのスクリプトが再実行された場合にのみ新しいページをカウントします。これは次の 2 つの条件で発生します。

* `Kameleoon.API.Core.enableSinglePageSupport()` が呼ばれ、URL の変更と組み合わされたとき。
* `Kameleoon.API.Core.load()` が明示的にトリガーされたとき。

上記のすべてのガイドラインに従うことで、SPA 全体でバリエーションが効果的かつ一貫して実装され、データの整合性を維持しながらユーザー体験を向上できます。追加の支援が必要な場合は、Kameleoon チームにお気軽にお問い合わせください。

## 代替手段

### REACT および JS SDK

Kameleoon は、シングルページアプリケーション向けに設計された [React SDK](../../../../developer-docs/sdks/web-sdks/react-js-sdk) と [JavaScript/TypeScript SDK](../../../../developer-docs/sdks/web-sdks/js-sdk) を提供しています。これらの SDK は、アプリケーションのコードベースに SDK を統合することで、SPA 内で実験を実行し、機能フラグを管理する代替方法を提供します。

SPA で利用可能な機能の完全なリストについては、[SDK ドキュメント](../../../../developer-docs/feature-experimentation/get-started/overview) を参照してください。

### GatsbyJS プラグイン

Kameleoon は GatsbyJS アプリケーション専用のプラグインも提供しています。Kameleoon を GatsbyJS アプリと統合するには、[この記事](https://www.gatsbyjs.com/plugins/gatsby-plugin-kameleoon/) に記載されている手順に従ってください。

### Next.js フレームワーク

ウェブサイトが Next.js で構築されている場合、Kameleoon の Graphic エディタを使用する際の重要な考慮事項があります。Next.js ウェブサイトは特定の方法でロードされるため、Kameleoon の変更が非常に迅速に行われると衝突が発生し、ページが正しく表示されない可能性があります。

#### 推奨される解決策

Kameleoon チームは、この問題を自動的に解決する専用の Next.js セットアップガイドを作成しました。このセットアップにより、以下が保証されます。

* Kameleoon は迅速かつ効率的にロードされます。
* ページがフリッカリングなしでスムーズに表示されます。
* サイトを壊すことなく、適切なタイミングで変更が表示されます。
* ページナビゲーションが正しく機能します。

**ステップバイステップガイドを参照:** [Next.js での実装](../../../../developer-docs/web-experimentation/implementation-and-deployment/implementation-with-nextjs)

#### 代替アプローチ

上記の推奨セットアップを使用できない場合、衝突を防ぐ他の方法があります。開発者は「ページが変更の準備ができた」ことを Kameleoon に伝えるシンプルなシグナルを追加できます。

* **方法 1: ページ準備完了インジケーター**
  * ページが完全にロードされたら、`<body>` 要素にマーカーを追加します。次に、このマーカーが存在するときにのみ Kameleoon 実験が実行されるように設定します。
* **方法 2: カスタムイベント**
  * Kameleoon のコマンドキューを使用して、ページが準備できたらシグナルを送信します: `Events.trigger('my page is hydrated')`。
  * 次に、このシグナルを待ってから変更を行うように、**Custom event** ターゲティング基準を使用するように実験を構成します。カスタムイベントとその他のターゲティングの実装に関する詳細については、[この記事](../../../assets/segments/create-a-segment#テクニカル) を参照してください。

<Note>
  専用の Next.js セットアップはこれらすべてを自動的に処理するため、これらの技術的な詳細について心配する必要はありません。
</Note>
