はじめに(写真は多いほど売れる?)
「商品ページの写真は多いほうが売れる」――EC運営に関わっていると、ほぼ定説のように語られるフレーズです。確かに、サイズ感やディテールが伝わる写真が多ければ、購入の不安は減りそうな気がします。
ただ、これを自分のショップのデータで確かめたことはあるでしょうか。「枚数を増やせば売れる」と信じて全商品の撮影を増やしたものの、効果がよく分からないまま工数だけかかった、という話もよく聞きます。幸い、写真枚数は商品マスタに、購買データはGA4にあります。両者を結合すれば、「写真枚数とCVRに関係があるのか」を自分の手で検証できます。
この記事では、商品マスタの写真枚数とGA4の view_item → purchase を結合し、枚数帯ごとのCVRを比べたり、相関係数を出したりする手順を紹介します。あわせて、この種の分析でいちばん大事な「相関と因果は違う」という落とし穴についても整理します。
なお、本記事で出てくる数値はすべて手順を説明するための**例(架空の値)**です。実際の傾向はショップごとに大きく異なります。
準備:必要なデータ
検証には2種類のデータが必要です。ひとつは商品マスタ。商品ID(item_id)ごとに、登録写真の枚数(photo_count)やカテゴリ(category)を持つテーブルで、多くのカートシステムからCSVやAPIで取得できます。これをBigQueryに product_master として取り込んでおきます。
もうひとつはGA4のBigQueryエクスポート。events_* テーブルに view_item(商品閲覧)と purchase(購入)が入っている前提です。商品単位で見るので、items 配列の item_id を使います。ここでは analytics_XXXXXX.events_* の形式でデータが入っているものとして進めます。
ステップ1:商品ごとのview_itemとpurchaseを集計する
まず、GA4のイベントから商品ごとの「閲覧数」と「購入数」を出します。ここで分母・分子の定義をきちんと決めておくことが大事です。
- 分母(閲覧数)=
view_itemの発生回数:その商品が何回見られたか。 - 分子(購入回数)= その商品が購入された取引(注文)の数:何回の注文にその商品が含まれたか。
そのうえで CVR = 購入回数 ÷ 閲覧数 を商品単位で計算します。
ここによくある落とし穴があります。GA4の purchase イベントは1注文につき1回だけ発生し、その中の items 配列に注文された複数商品がぶら下がっています。items を UNNEST してから単純に COUNTIF(event_name = 'purchase') で数えると、1回の注文が商品の行数ぶん重複カウントされ、複数商品をまとめ買いした注文ほど購入回数が水増しされてしまいます(その結果CVRの分子が過大になる)。
これを避けるには、購入回数を取引IDで重複なく数えます。GA4には注文ごとに一意な ecommerce.transaction_id があるので、商品×取引でユニーク化した COUNT(DISTINCT transaction_id) を分子にします。一方、view_item には取引IDがないので、こちらは発生回数(行数)をそのまま数えます。
-- 商品ごとの閲覧数・購入回数を集計
WITH item_events AS (
SELECT
event_name,
item.item_id AS item_id,
ecommerce.transaction_id AS transaction_id -- purchase のみ値が入る
FROM
`analytics_XXXXXX.events_*`,
UNNEST(items) AS item
WHERE
_TABLE_SUFFIX BETWEEN '20260601' AND '20260731'
AND event_name IN ('view_item', 'purchase')
)
SELECT
item_id,
-- 分母:view_item の発生回数(行数)
COUNTIF(event_name = 'view_item') AS view_cnt,
-- 分子:その商品が購入された取引数を重複なく数える
-- (items 展開で 1 注文が複数行になっても transaction_id でユニーク化)
COUNT(DISTINCT IF(event_name = 'purchase', transaction_id, NULL)) AS purchase_cnt,
SAFE_DIVIDE(
COUNT(DISTINCT IF(event_name = 'purchase', transaction_id, NULL)),
COUNTIF(event_name = 'view_item')
) AS cvr
FROM item_events
GROUP BY item_id
COUNT(DISTINCT ...) の中で IF(event_name = 'purchase', transaction_id, NULL) としているのは、view_item 行の transaction_id(NULL)を分子から除外しつつ、同じ商品が同じ注文内に複数行で現れても1回として数えるためです。これで分子は「その商品が含まれた注文の数」になります。
SAFE_DIVIDE を使っているのは、閲覧が0件の商品でゼロ除算エラーにならないようにするためです。ここで出る cvr は「閲覧1回あたり、その商品が注文に至った割合」で、商品ページの成約力を表す指標として使います。
ステップ2:写真枚数を結合する
次に、ステップ1の集計結果に商品マスタの写真枚数を結合します。item_id をキーにして JOIN するだけです。
-- 写真枚数を結合
WITH item_cvr AS (
-- ステップ1のクエリをそのままここに入れる(item_id, view_cnt, purchase_cnt, cvr を返す)
...
)
SELECT
c.item_id,
m.photo_count,
c.view_cnt,
c.purchase_cnt,
c.cvr
FROM item_cvr AS c
JOIN `your_dataset.product_master` AS m
ON c.item_id = m.item_id
WHERE c.view_cnt >= 100 -- 閲覧が少なすぎる商品はノイズになるので除外
ポイントは最後の WHERE c.view_cnt >= 100 です。閲覧が数件しかない商品は、購入が1件あるだけでCVRが極端に跳ね上がります。サンプル数が小さい商品を混ぜると相関が歪むので、一定以上の閲覧がある商品だけに絞るのが安全です。しきい値はデータ量に応じて調整してください。
ステップ3:枚数帯別のCVRを出す
商品単位のCVRはばらつきが大きいので、写真枚数を「帯(バケット)」にまとめて平均CVRを比べます。ここでは、ステップ2の結果を item_cvr_with_photo というテーブルに保存した前提で進めます。
-- 写真枚数帯ごとの平均CVR
WITH joined AS (
SELECT item_id, photo_count, view_cnt, purchase_cnt, cvr
FROM `your_dataset.item_cvr_with_photo`
)
SELECT
CASE
WHEN photo_count <= 2 THEN '1: 1〜2枚'
WHEN photo_count BETWEEN 3 AND 5 THEN '2: 3〜5枚'
WHEN photo_count BETWEEN 6 AND 9 THEN '3: 6〜9枚'
ELSE '4: 10枚以上'
END AS photo_bucket,
COUNT(*) AS item_cnt,
SUM(view_cnt) AS total_view,
SAFE_DIVIDE(SUM(purchase_cnt), SUM(view_cnt)) AS bucket_cvr
FROM joined
GROUP BY photo_bucket
ORDER BY photo_bucket
帯ごとに cvr を単純平均するのではなく、SUM(purchase_cnt) / SUM(view_cnt) で帯全体のCVRを出している点に注意してください。商品単位のCVRを平均すると、閲覧の少ない商品も同じ重みで効いてしまい、実態とズレます。
結果は例えば次のようになります(数値はすべて架空の例)。
photo_bucket item_cnt total_view bucket_cvr
1: 1〜2枚 120 45,000 1.8%
2: 3〜5枚 210 98,000 2.4%
3: 6〜9枚 150 62,000 2.9%
4: 10枚以上 40 15,000 2.7%
この例だと「枚数が増えるとCVRも上がるが、10枚を超えると頭打ち」という傾向に見えます。ただし、これだけで結論を出すのは早すぎます。
ステップ4:相関係数(CORR関数)を出す
帯別の傾向に加えて、商品単位での相関の強さも見ておきます。BigQueryには CORR 関数があり、2つの数値列のピアソン相関係数を一発で計算できます。
-- 写真枚数とCVRの相関係数
SELECT
CORR(photo_count, cvr) AS corr_photo_cvr,
COUNT(*) AS sample_size
FROM `your_dataset.item_cvr_with_photo`
WHERE view_cnt >= 100
CORR の結果は -1〜+1 の値を取ります。+1に近いほど「写真が多いほどCVRが高い」という正の相関が強く、0に近ければほぼ無関係、マイナスなら逆の関係です。
例えば corr_photo_cvr = 0.18 のような値が出たとします(これも架空の例です)。これは「弱い正の相関がある」程度の数字で、「写真を増やせばCVRが上がる」と言い切れるほど強い関係ではありません。相関係数は必ずサンプルサイズ(sample_size)とセットで見て、商品数が十分にあるかも確認してください。
⚠️ 相関≠因果(ここがいちばん大事)
ここまでで「写真枚数とCVRに弱い正の相関がありそう」という結果が得られたとします。でも、ここで「だから写真を増やせば売れる」と結論づけるのは危険です。相関があることと、因果があることはまったく別だからです。
このケースで真っ先に疑うべきは**交絡(こうらく)**です。交絡とは、写真枚数とCVRの両方に影響している「第3の要因」が裏に隠れているせいで、見かけ上の相関が生まれてしまう現象です。EC商品ページでありがちな交絡を挙げます。
- 人気商品ほど写真が多い:売れ筋の主力商品は、撮影に予算をかけて写真をたくさん用意しがちです。つまり「売れているから写真が多い」のであって、「写真が多いから売れる」とは限りません。因果が逆向きの可能性があります。
- カテゴリの違い:アパレルや家具のように「見た目で選ぶ商品」は写真が多く、かつCVRの傾向も特殊です。カテゴリごとの差が、枚数とCVRの相関に紛れ込みます。
- 価格帯:高単価商品ほど写真を充実させる一方で、CVR自体は低くなる傾向もあります。価格を無視すると相関の解釈を誤ります。
これらを無視して全商品をまとめて相関を取ると、「写真の効果」と「商品自体の人気やカテゴリの効果」がごちゃ混ぜになり、出てきた数字は写真の効果そのものを測れていない可能性が高くなります。
相関は「2つの数字が一緒に動いている」ことしか教えてくれません。「片方を動かせばもう片方も動く」という保証はどこにもない、というのは分析の鉄則です。
交絡を減らす工夫
完全に因果を証明するのは簡単ではありませんが、交絡の影響を減らす工夫はできます。ひとつは、条件をそろえて比較すること。同じカテゴリ・同じ価格帯に絞って相関を見ると、商品特性の差が小さくなり、写真の効果を切り出しやすくなります。
-- カテゴリ・価格帯をそろえてから相関を見る
SELECT
category,
CORR(photo_count, cvr) AS corr_in_segment,
COUNT(*) AS sample_size
FROM `your_dataset.item_cvr_with_photo`
WHERE view_cnt >= 100
AND price BETWEEN 3000 AND 5000
GROUP BY category
HAVING sample_size >= 30
HAVING sample_size >= 30 で商品数が少なすぎる層は除いています。層を細かく切るほどサンプルが減って相関が不安定になるので、ここのバランスは大事です。
もうひとつは、観察データだけで結論を出さず、A/Bテストで確かめること。同じ商品ページで写真枚数だけを変えた2パターンをランダムに出し分けてCVRを比べれば、写真の効果をかなりクリーンに測れます。相関分析は「どの商品でテストすべきか」のあたりをつける入口、と捉えるのが現実的です。
示唆と次の検証
ここまでで得られるのは、「写真枚数とCVRに弱い正の相関はありそうだが、それが写真の効果だとは断定できない」というところまでです。控えめに聞こえますが、これが誠実な結論です。ここから先に進めるなら、次のステップが考えられます。
- 層別に相関を取り直す:カテゴリ・価格帯をそろえても相関が残るか確認する。残れば写真の効果である見込みが上がります。
- 写真の「質」も見る:枚数だけでなく、用途別カット(着用イメージ、サイズ表、ディテール)が揃っているかという中身の指標を足す。
- A/Bテストで検証する:相関が強く出た層の代表商品で、写真枚数だけを変えて実測する。
- 離脱との関係も見る:写真が少ない商品ページで離脱が多いなら、改善の優先度がはっきりします。商品ページの離脱分析はこちらの記事で扱っています。
写真枚数のように「マスタの属性 × GA4の行動データ」を結合する分析は応用範囲が広く、同じ枠組みは返品率の分析にも使えます。カテゴリ別の返品傾向を見たい方は返品率の分析記事も参考にしてください。
まとめ
商品ページの写真枚数とCVRの関係は、商品マスタとGA4を結合すれば自分のショップのデータで検証できます。
- 商品ごとに
view_item→purchaseを集計し、写真枚数をJOINしてCORR関数で相関を見る - ただし相関は因果ではない。人気商品ほど写真が多い、といった交絡を疑う
- カテゴリ・価格帯をそろえる、A/Bテストで確かめる、といった工夫で因果に近づける
「写真は多いほど売れる」を鵜呑みにせず、まず自分のデータで相関を見て、本当に効きそうな仮説だけをテストにかける――データを見る前に撮影工数を全商品に投じるより、ずっと費用対効果の高い進め方になるはずです。