こんにちは山本です。
どのデバイスでどこに住む、どこのページから流入したユーザがどこを回遊し、
どこをクリックし、どの順番にどのようにフォームを入力しCVするのか
または離脱したのか
これを定量的に知る術をみなさんあまり知りません。
上場企業でもメガベンチャーでもベンチャーでも
意外とそのような分析体制がないことを知っています。
いつもここから整理するからです。
以下、私がいつもやることを書きますが、
googleのエンジニアやマーケターに聞いてもこれが答えだということだったので
おそらくそれなりに筋は良いかと思います。
どのように行動分析をできるようにするのか
まず、サイトのすべてのページにページID、
パーツにpart番号を振っていきます。

こういう感じで、このページを開いたらページ種別がTOPで、
そのこの部分をクリックしたらpart_idが34番などと
全てにdata属性を振っておき、それをGTMの変数を作りbigqueryに送信します。
コードで見るとこんな感じになります。

そして全ページに
リードステータス
ゲストID
流入時のutmパラメーター
DBのユーザID
ページ種別
デバイス
パートID
などを
定義します。

上記は一部です。
そしてこれをGTMの変数として定義し、bigqueryに飛ばします。
bigqueryでは

このようなsqlで特定の期間の行動履歴を出すことができます。
そして取得した行動履歴を
吐き出したものがこちらです

これができたら、
例えば一例でgasスクリプトを記載しますが
/**
* "results-20250603-151144" シートの C 列に '"part":"98"' または '"part":"99.1"' を含む行を抽出し、
* "cta_click_user_list" シートにコピーします。
*/
function extractRowsByPartInColumnC() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var srcSheetName = 'results-2xx3-5xx4';
var dstSheetName = 'cta_click_user_list';
// ソースシート取得
var srcSheet = ss.getSheetByName(srcSheetName);
if (!srcSheet) {
SpreadsheetApp.getUi().alert('シート "' + srcSheetName + '" が見つかりません。');
return;
}
// 抽出先シートを取得 or 新規作成
var dstSheet = ss.getSheetByName(dstSheetName);
if (dstSheet) {
dstSheet.clearContents();
} else {
dstSheet = ss.insertSheet(dstSheetName);
}
// 全データを取得
var values = srcSheet.getDataRange().getValues();
var output = [];
for (var i = 0; i < values.length; i++) {
var row = values[i];
var cCell = row[2]; // C列はインデックス 2
if (cCell == null) continue;
var text = cCell.toString();
if (text.indexOf('"part":"98"') !== -1 || text.indexOf('"part":"99.1"') !== -1) {
output.push(row);
}
}
if (output.length === 0) {
SpreadsheetApp.getUi().alert('該当する行が見つかりませんでした。');
return;
}
// 抽出結果を A1 から書き込む
dstSheet.getRange(1, 1, output.length, output[0].length).setValues(output);
SpreadsheetApp.getUi().alert('抽出完了:' + output.length + ' 行を "' + dstSheetName + '" シートにコピーしました。');
}
/**
* "cta_click_user_list" シートの C 列から gid を抽出し、
* 同じ行の I 列に書き込みます。
*/
function get_gid_from_cta_click_user() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = 'cta_click_user_list';
var sheet = ss.getSheetByName(sheetName);
if (!sheet) {
SpreadsheetApp.getUi().alert('シート "' + sheetName + '" が見つかりません。');
return;
}
// シートの最終行を取得
var lastRow = sheet.getLastRow();
if (lastRow < 1) return;
// C列のデータを取得(1 行目から最終行まで)
var cRange = sheet.getRange(1, 3, lastRow, 1);
var cValues = cRange.getValues();
// I列に書き込むための2次元配列を準備
var output = [];
for (var i = 0; i < cValues.length; i++) {
var cellText = cValues[i][0];
var gid = '';
if (cellText && typeof cellText === 'string') {
// '{"uid":0,"gid":"' で分割
var parts = cellText.split('{"uid":0,"gid":"');
if (parts.length > 1) {
// 2番目の要素を先頭の '"' で再分割して gid を抽出
var remainder = parts[1];
var secondParts = remainder.split('"');
if (secondParts.length > 0) {
gid = secondParts[0];
}
}
}
output.push([gid]);
}
// I列に一括で書き込む
sheet.getRange(1, 9, output.length, 1).setValues(output);
}
/**
* "cta_click_user_list" シートの I 列の値を重複を除いて
* J 列に書き出します。
*/
function get_nayose_merge_cta_click_usa() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = 'cta_click_user_list';
var sheet = ss.getSheetByName(sheetName);
if (!sheet) {
SpreadsheetApp.getUi().alert('シート "' + sheetName + '" が見つかりません。');
return;
}
// I列の最終行を取得
var lastRow = sheet.getLastRow();
if (lastRow < 1) return;
// I列(9列目)のデータを1行目から最終行まで取得
var iValues = sheet.getRange(1, 9, lastRow, 1).getValues();
// 重複を排除するセットを作成
var uniqueSet = new Set();
for (var i = 0; i < iValues.length; i++) {
var val = iValues[i][0].toString().trim();
if (val !== '') {
uniqueSet.add(val);
}
}
// セットを配列に変換し、2次元配列に整形
var uniqueArray = Array.from(uniqueSet).map(function(item) {
return [item];
});
// J列(10列目)に書き込み
if (uniqueArray.length > 0) {
sheet.getRange(1, 10, uniqueArray.length, 1).setValues(uniqueArray);
}
}
/**
* "cta_click_user_list" シートの J 列の gid を一つずつ取得し、
* "results-20250603-151144" シートの C 列を検索して
* 当該 gid に対して '"cv":"1"' が一度も出現しない場合、
* cta_click_user_list シートの同じ行の K 列に gid を書き込みます。
*/
function get_not_cv_user_from_cta_list() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ctaSheetName = 'cta_click_user_list';
var resultsSheetName = 'results-20250603-151144';
var ctaSheet = ss.getSheetByName(ctaSheetName);
if (!ctaSheet) {
SpreadsheetApp.getUi().alert('シート "' + ctaSheetName + '" が見つかりません。');
return;
}
var resultsSheet = ss.getSheetByName(resultsSheetName);
if (!resultsSheet) {
SpreadsheetApp.getUi().alert('シート "' + resultsSheetName + '" が見つかりません。');
return;
}
// cta シートの最終行を取得
var ctaLastRow = ctaSheet.getLastRow();
if (ctaLastRow < 1) return;
// J列(10列目)のデータを取得(1行目~最終行まで)
var jValues = ctaSheet.getRange(1, 10, ctaLastRow, 1).getValues();
// results シートの最終行を取得
var resultsLastRow = resultsSheet.getLastRow();
var resultsCValues = [];
if (resultsLastRow >= 1) {
// C列(3列目)のデータを取得(1行目~最終行まで)
resultsCValues = resultsSheet.getRange(1, 3, resultsLastRow, 1).getValues();
}
// K列(11列目)に出力するための配列を用意
var output = [];
for (var i = 0; i < ctaLastRow; i++) {
var gid = (jValues[i][0] || '').toString().trim();
if (gid === '') {
// J列が空なら K列も空
output.push(['']);
continue;
}
// results の C列を検索して、同一 gid かつ '"cv":"1"' を含む行があるかチェック
var hasCvOne = false;
var searchPattern = '"gid":"' + gid + '"';
for (var r = 0; r < resultsCValues.length; r++) {
var text = (resultsCValues[r][0] || '').toString();
if (text.indexOf(searchPattern) !== -1 && text.indexOf('"cv":"1"') !== -1) {
hasCvOne = true;
break;
}
}
if (hasCvOne) {
// '"cv":"1"' が見つかった → K列は空
output.push(['']);
} else {
// '"cv":"1"' が一度も見つからなかった → K列に gid を書き込む
output.push([gid]);
}
}
// K列(11列目)に一括で書き込む
ctaSheet.getRange(1, 11, output.length, 1).setValues(output);
}
つまり行動履歴からさまざまなパターンのユーザを抽出します。
CVしたユーザだけでなく、
見積もりボタン押したのに、CVしなかったユーザ
などの一連のこうどうの履歴を出していきます。
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”LIST”,”pre”:”LIST”,”l_id”:5,”cv”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”utm”:””,”LD”:”7″,”l_id”:5,”device”:”PC”} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”LIST”,”l_id”:5,”part”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”LIST”,”pre”:”LIST”,”l_id”:5,”cv”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”utm”:””,”LD”:”7″,”l_id”:5,”device”:”PC”} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”LIST”,”l_id”:5,”part”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”utm”:””,”LD”:”7″,”l_id”:5,”device”:”PC”} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”LIST”,”l_id”:5,”part”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”LIST”,”pre”:”CAR”,”l_id”:5,”cv”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”CAR”,”pre”:”DET”,”l_id”:25,”cv”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”utm”:””,”LD”:”15″,”l_id”:25,”device”:”PC”} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”CAR”,”l_id”:25,”part”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”act”:”1″,”cv”:”0″,”part”:”98″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”act”:”1″,”cv”:”0″,”part”:”96″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”act”:”1″,”cv”:”0″,”part”:”93″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”act”:”1″,”cv”:”0″,”part”:”93″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”act”:”1″,”cv”:”0″,”part”:”94″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”act”:”1″,”cv”:”0″,”part”:”94″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”pre”:”DET”,”l_id”:20,”cv”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”utm”:””,”LD”:”10″,”l_id”:20,”device”:”PC”,”p_id”:”8545″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”part”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”pre”:”DET”,”l_id”:20,”cv”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”utm”:””,”LD”:”10″,”l_id”:20,”device”:”PC”,”p_id”:”8571″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:20,”part”:”0″} |
{“uid”:0,”gid”:”NslfRtF3″,”pg”:”DET”,”l_id”:”15″,”act”:”1″,”cv”:”0″,”part”:”2006″} |
そして、定義の際にpartに説明をつけた内容とGPTにプロンプトをなげると
【コンバージョン未達ユーザーAの動き】
gid = “NslfRtF3”
uid = 0(未ログイン / CVに至らず)
◾️概要
PC利用、東京都(三鷹市)およびドイツ(フランクフルト)からのアクセスが確認されたユーザー。
自然検索(utm空)から、商品ID: 8545・8571・4967・8489 など複数の商品詳細ページ(pg: DET)にたびたび流入。
サイズ(part 93)や注文数(96)、価格表(94)、見積もり発行(98)といった購入直前アクションまでは実行しているが、ログインもせず、最終的にCVには至らなかった。
テンプレートのダウンロード(part 100)や最近チェックした商品からの再訪(112)もあり、購買意欲は非常に高いユーザーと推察される。
◾️ユーザー行動自然言語化詳細(全アクセス履歴)
🕓 2025-05-25(東京都 三鷹市)
- 10:17:17|自然検索から、**商品詳細ページ(商品ID: 8545)**へ初回流入。
- 10:17:22|商品詳細ページ(p_id: 8545)を再読込(part: 0)。
- 10:17:30〜10:17:38|FV画像(part: 90)を複数回クリック。商品画像を確認中。
- 10:35:03|おすすめ商品からの導線(part: 111)をクリックして別商品へ。
- 10:35:10|商品ID: 4967 の商品詳細ページに遷移。
- 10:35:37|最近チェックした商品からの導線(part: 112)をクリック → 再び商品詳細へ戻る。
- 10:35:43|商品詳細ページ(p_id: 8545)に再訪。FV画像クリック継続(part: 90)。
- 15:54:47|テンプレートをダウンロード(part: 100)→ この時点で強い購入検討が伺える。
✈️ 2025-05-28(ドイツ Hessen州 Frankfurt)
- 13:02:09|再びテンプレートをダウンロード(part: 100)→ 商品ID: 8545 の詳細ページ。
- 14:14:15|商品ID: 8571 の詳細ページを読み込み。
- 14:14:26|商品ID: 8545 に戻る。FV画像再チェック(part: 90)。
- 14:14:41|サイズ(part: 93)、価格表(94)、注文数(96)などをクリック。
- 14:15:11|見積もり発行検討(part: 98)。
- 14:15:17|カートページに遷移するも、そのまま離脱(CVなし)。
🕓 2025-05-31(東京都 三鷹市)
- 22:21:00〜22:21:26|再度、商品ID: 8545 の詳細ページにアクセス。
FV画像(part: 90)を繰り返しクリックするが、新たな進展は見られず。
📍 位置情報まとめ
日時 | ロケーション | 行動内容 | 商品ID(p_id) |
---|---|---|---|
5/25 午前 | 三鷹市 | 初回流入〜導線クリック | 8545 → 4967 → 8545 |
5/25 午後 | 三鷹市 | テンプレDL(part: 100) | 8545 |
5/28 午後 | Frankfurt | サイズ・価格・見積り・カートへ遷移 | 8571 → 8545 |
5/31 夜 | 三鷹市 | FV画像クリックのみ | 8545 |
◾️まとめと示唆
このユーザーは、
- 商品ID: 8545 を中心に、複数の商品を国内外から繰り返し確認。
- テンプレDL、見積もり検討、カート画面到達までしており、購買意志は非常に高い。
- ただし、**ログインせず(uid = 0)**情報入力にも進んでいないため、購入に至らず終了。
📌 施策提案:
- ログイン誘導や「お気に入り保存」導線の強化
- 見積り or カート放棄ユーザーへのリマインド通知
- ロケーションに応じた通貨表示/配送条件表示(国際アクセス対策)
このような行動が丸わかりになる記述を取得できます。
これまではbigqueryの値をredshiftに送って分析などをやっていましたが
結局「費用はなんでも抑えたい/無料の範囲でやりたい」という人が多いのではないかと思います。
そのため、日にちを限定して上記のような方法でbigqueryから定義されたjsonを取得し
定義されたサイトのパートとストーリーをGPTのプロンプトにすれば
だいぶ細かくストーリー性をもった分析ができるようになります。
ちなみにサムネイルはバンコク法人の梶村です。