こんにちは!ASUE株式会社Webコンサルタントのコバヤシです!
LPにiframeで埋め込んだ外部フォーム(今回はform-mailer)の送信完了を、コンバージョンとして計測したい。よくある要件ですが、親ページとフォームのドメインが異なる「クロスオリジン」の状態だと、一筋縄ではいきません。
以前、ASUE通信でもこのテーマを取り上げたことがあります。
前回の方法はフォーム提供元(iframe側)にもGTMを設置する必要があり、お客さま側のご協力や管理画面の権限などが必要で、対応が難しい場合もありました。
今回はLP本体側の設定だけで完結する方法がないかの検討を行い、いくつか試した結果なんとか計測ができたので、その過程と結果を共有します。
なお、今回の案件ではLP本体の中にform-mailer(business.form-mailer.jp)のフォームページがiframeとして埋め込まれていました。(こちらのサービスにはGTMの設置機能があるため、編集権限等があれば上述記事の方法も可能です。)
目次
検討した手段と断念した理由
解決策にたどり着くまでに、6つの方法を検討しました。順番に紹介します。
手段1: GTM「要素の表示」トリガー
フォーム送信完了後に表示される「回答の送信が完了しました。」というテキストを監視してCVを発火させる方法を検証しました。
断念理由
GTMの「要素の表示」トリガーはIDまたはCSSセレクターによる指定のみ対応しており、テキスト内容での直接指定はできません。
また、詳しくは後述しますが、テキスト要素自体がiframe内にあるため、親ページとドメインが異なるクロスオリジンの状態では取得できませんでした。
手段2: MutationObserverによるDOM監視
JavaScriptのMutationObserver APIでDOMの変化を監視し、完了テキストの表示をトリガーにする方法を検証しました。
断念理由
監視対象のDOM要素がiframe内にあるため、こちらもクロスオリジン制限でアクセスできません。
手段3: iframeのsrc属性変化の監視
フォーム送信後にiframeのsrc属性がサンクスページのURLに変わることを検知する方法を検証しました。
断念理由
iframeが内部でページ遷移してもsrc属性は最初に設定された値のまま変わらない仕様です。iframe内のURLは contentWindow.location.href からも取得できません(クロスオリジン制限)。
手段4: loadイベントのカウント方式
iframeのloadイベントが何回発火したかをカウントし、3回目(=送信完了ページ)でCVを発火させる方法を検証しました。
断念理由
「戻る」ボタンを押した場合にloadカウントがずれ、誤発火のリスクがあります。
入力画面(load1) → 確認画面(load2) → 戻る(load3)→誤発火→ 確認画面(load4) → 送信完了(load5) → 無反応
手段5: form-mailerのリダイレクト設定
form-mailerの管理画面で、送信完了後に専用のサンクスページへリダイレクトさせ、そのURLをGTMで検知する方法を検証しました。
断念理由
方法としては可能そうですが、クライアント側へのサンクスページの設置依頼が必要なこと、フォームの管理画面の権限をいただいていなかったことなどの理由から、今回の検討の趣旨に反するため断念しました。
手段6: postMessageの監視
form-mailerが送信完了時に親ページへpostMessageを送信していれば、それを検知する方法を検証しました。
断念理由
DevToolsでpostMessageの受信を監視しましたが、iframeの高さ変更のメッセージのみ確認でき、コンバージョンに至ったことがわかるメッセージの受信は確認できませんでした。
整理:クロスオリジンで何ができて何ができないか
クロスオリジンiframeに対してで親ページからできること・できないことを整理すると、以下のとおりです。
| アクセス内容 | 同一オリジン | クロスオリジン |
|---|---|---|
| iframe内のDOM要素を取得する | 可能 | 不可 |
| iframe内のURLを取得する | 可能 | 不可 |
| iframe内でのsubmit/clickイベントを検知する | 可能 | 不可 |
| iframe要素自体の属性(高さ・幅など)を取得する | 可能 | 可能 |
| iframeのloadイベントを検知する | 可能 | 可能 |
| iframeのpostMessageを検知する | 可能 | 可能 |
| iframe内のCookieにアクセスする | 可能 | 不可 |
| iframe内のlocalStorageにアクセスする | 可能 | 不可 |
親ページとiframe内のページでドメインが異なる場合、ブラウザのセキュリティポリシー(同一オリジンポリシー)により、親ページからiframe内部の情報へのアクセスが制限されます。
この制限のために、今回検証した方法では測定ができませんでした。
採用した解決策:iframeの高さ変化による検知
手段6でpostMessageの検知を実施したところ、送信ステップごと(送信画面・確認画面・戻るを押したタイミング・完了画面)に高さを変更するメッセージを送信していることがわかりました。
postMessageの有無に関わらず、クロスオリジン制限があってもiframe要素自体の高さの変化は親ページからでも取得可能です。
今回のLPのフォームでは、フォームの各画面で高さが大きく異なっていたことに着目しました。
各画面の高さ計測結果
DevToolsのコンソールで以下のコマンドを実行して高さを実測しました。

const iframe = document.querySelector('iframe');
const ro = new ResizeObserver((entries) => {
for (const entry of entries) {
console.log('height:', entry.contentRect.height);
}
});
ro.observe(iframe);
上記のコードをコンソールに入力すると、その後iframeの高さ変動を監視してくれます。入力画面の状態でコードを入力→その後フォーム送信を行うと、各画面の高さを確認できます。
| 画面 | 高さ |
|---|---|
| 入力画面 | 601px |
| 確認画面 | 669px |
| 完了画面 | 1127px |
完了画面だけ高さが1127pxと突出して大きくなります。これを利用してCVを検知する方針に決めました。(デバイスによっても変動する可能性があるため、検証等の必要がありますが今回の説明では割愛しています。)
ちなみに、コンソールにコードを入力するときは、どんな処理を行っているかきちんと理解して行いましょう。(処理内容を理解しないでコピペを行っていると、場合によっては攻撃に悪用される可能性があります!)
判定ロジック
- 入力画面(601px)と確認画面(669px)はどちらも1000px未満
- 完了画面(1127px)だけが1000px以上
- → iframeのloadイベント発火後、高さが1000px以上なら完了画面と判定
実装コード(GTM カスタムHTMLタグ)
loadイベント発火後のiframeの高さによって、完了画面を判定するコードです。(設定方法の詳細は後述)
<script>
(function() {
var iframe = document.querySelector('iframe[src*="form-mailer.jp"]');
if (!iframe) return;
var firedCv = false; // 重複発火防止フラグ
iframe.addEventListener('load', function() {
if (firedCv) return;
setTimeout(function() {
var h = iframe.offsetHeight;
if (h > 1000) { // 完了画面のみ1000px超過
firedCv = true;
window.dataLayer = window.dataLayer || [];
dataLayer.push({ event: 'form_cv' });
}
}, 500); // embed.jsのリサイズ完了を待つ
});
})();
</script>
重複発火・誤発火の検証
| シナリオ | 挙動 |
|---|---|
| 入力画面表示 | 高さ601px→発火しない |
| 確認画面表示 | 高さ669px→発火しない |
| 「戻る」ボタン押下 | 高さ669pxから601px→発火しない |
| 送信完了画面表示 | 高さ1127px→発火する |
| ページをリロードせずに2回目以降の送信完了 | firedCvフラグで発火しない |
GTM設定手順
Step 1: カスタムHTMLタグの作成
- GTM → タグ → 新規
- タグタイプ:カスタムHTML
- 上記のコードを貼り付け
- トリガー:All Pages(ページビュー)
- タグ名:「iframe 高さ監視 CV検知」で保存
Step 2: カスタムイベントトリガーの作成
- GTM → トリガー → 新規
- トリガータイプ:カスタムイベント
- イベント名:
form_cv(※イベント名は任意) - 保存
Step 3: CVタグへの紐付け
- 該当のCVタグ(Google広告 / GA4など)を開く
- トリガーをStep 2で作成したものに変更
- プレビューモードで動作確認後、本番公開
動作確認方法
GTMプレビューモードで確認
- GTM → プレビュー をクリック
- LPのURLを入力して接続
- フォームを 入力 → 確認 → 送信 の順に操作
- GTMプレビューパネルで
form_cv(※任意で設定したイベント名)イベントの発火を確認
dataLayerの直接確認
送信完了後、DevToolsのコンソールで以下を実行します。
dataLayer.filter(d => d.event === 'form_cv')
// → [{event: "form_cv"}] が返れば成功
注意点と今後の対応
今回は、LP側に埋め込んだGTMの権限のみでコンバージョンの計測が可能かという検証のために実装しました。form-mailerでは、高さの変化による検知が可能でしたが、サービスによっては同じ方法でできない場合もあるでしょう。また、すこし触れましたが閲覧するデバイス環境によっても高さの変動の可能性があるため、そこの検証や調整も必要です。
iframeの高さに依存しているため、form-mailer側のデザイン変更等で高さが変わると計測が機能しなくなるリスクがあります。以下の対応を推奨します。
- フォーム側の管理画面の権限をいただき、別の計測方法を検討する(最良)
- 定期的にテスト送信を行い、CV計測が正常に動いているか確認する
- form-mailerのデザイン変更時はiframeの高さを再計測する
- Google広告やGA4でコンバージョン数が急減した場合のアラートを設定しておく
まとめ
クロスオリジンiframeでは、iframe内部のDOM要素やURLを親ページから取得できないため、一般的なCV計測の手法がほとんど使えません。しかし、iframe要素自体の高さ(offsetHeight)は親ページからでも取得可能です。今回はこの性質を利用し、loadイベント発火後にiframeの高さを判定することで、LP側のGTMだけで送信完了を検知する方法を実現しました。
ただし、高さの閾値や判定条件は使用するフォームの実装・デザインによって異なります。同じform-mailerであっても案件ごとに各画面の高さを実測し、条件を調整する必要があります。
あくまで正攻法はリダイレクト設定(手段5)やiframe側へのGTM設置です。権限や環境の制約でそれらが難しい場合に、可能かどうか検証の上、選択肢のひとつにしてもらえればと思います。
ASUEでは、Web広告運用を軸としたWebマーケティング支援全般を行っています。運用や計測にお悩みの方は、ぜひ資料請求だけでもお気軽にご活用ください!
売り上げを増やすためのWeb広告成功事例集
- CVは付くものの成約に繋がらない
- 今の代理店に不満がある
- 専任担当者がおらず知見・時間が無い
- そもそも広告で成果が出ない

上記のようなお悩みを持った方へ
すぐに役立つASUEの広告改善事例を紹介します!
この記事を書いた人
コバヤシ
2022年新卒入社で、現在Webコンサルティング課所属。
小学生の頃に親がホットケーキにハマって週5でホットケーキを食べ続けたのが少しトラウマ。
