BLOGShopifyカスタマイズ事例4:最近チェックした商品
 
			POST DATE:2025/02/07
Shopifyカスタマイズ事例4:最近チェックした商品
ECの利益向上に繋がるShopifyカスタマイズ事例4
弊社ではShopifyでの制作をはじめ、様々なECサイトの制作のご依頼をいただいています。
特に、現在のECサイトの売上をUPしつつ効率的な運用を行いたい、月商を1,000万円以上の規模に成長させたい、月商億円規模のサイトを安全にシステム移管したい等、「利益を上げる知識」と「システム構築の知識」を総合的に持つことで解決できるご要望を、ワンストップで実現することを得意としています。
その現場の中で行ってきたカスタマイズ事例について、解説します。
事例4:最近チェックした商品のカスタマイズ
カスタマイズの背景
ECサイトでよく利用される最近チェックした商品(閲覧履歴)の有無は、商品購入率を向上するための基本施策です。しかしながら、Shopifyでは公式でそのようなLiquidタグや機能が用意されている形ではないため、通常ではテーマ固有のSectionパーツの有無や、アプリに頼るケースが多いと思います。
弊社ではより効果的な運用をするべく、独自のJavaScriptを利用し、自由な箇所への「最近チェックした商品」パーツ導入を実現しています。
Tips:ECで効果の高まる「最近チェックした商品」の配置箇所
最近チェックした商品は、商品を複数閲覧しながらの検討や、サイトへの再訪時にクリック率および購入率が高まる傾向にあります。そのため、その際によく利用される商品詳細の下部や、TOPやドロワーなど再訪時に閲覧する箇所に設置することで、高い効果を発揮します。
- 各商品詳細ページの下部
- TOPページのメインスライダー下などコンテンツ上部
- スマートフォンのドロワーメニュー内
- ブログ記事
カスタマイズ前の課題
- 最近チェックした商品のパーツが無いテーマを利用していた。
- 不要なアプリの増加による、サイトのスピード低下を防ぎたい。
- 任意の箇所への最近チェックした商品の表示をしたい。
- 月額費用のアップを抑えたい。
- 表示内容についての自由度が必要だった。
上記の課題から、アプリの機能に頼らず、テーマへのJavaScriptとLiquid開発での課題解決に取り組みました。
カスタマイズでの要件
- JavaScriptとLiquid側での開発
- どこでも指定箇所に利用できるようなコード的な自由度を用意
- 表示内容を変更できるような手法を用意
- 導入・表示にアプリを利用しない実装法を用意
カスタマイズでの解決案
上記要件を受けて、弊社では下記の解決案を用意し、カスタマイズ実装を行いました。
- JavaScriptでローカルストレージに閲覧した商品情報を格納
- 格納した商品情報を任意の形に整形し表示
- 同一の商品は格納しないような条件設定
- 任意の箇所に設置できる形式
- アプリを利用せず、コスト節約と速度影響の懸念を解消
実装方法
具体的に行った実装方法は下記のような方法を利用しています。
※各コードは例であり、各パーツへの機構を組み込むサンプルのため、あくまで機構づくりの参考として記載しています。
JavaScriptコード
このコードを、サイト全体に適用するように設置します。
<script>
function setRecentlyViewedProducts() {
  const title = "{{ product.title }}".trim(); 
  if (!title) {
	return;
  }
  const productData = {
	productTitle: "{{ product.title }}",
	productImg: "{{ product.featured_media | img_url: '800x' }}",
	productImgsnd: "{%- if product.images[1] != blank -%}{{- product.images[1] | img_url: '800x' -}}{%- else -%}{{- product.featured_media | img_url: '800x' -}}{%- endif -%}",
	productPrice: "{{ product.price | money }}",
	productUrl: "{{ product.url }}",
	productImageAltText: "{{product.featured_media.alt | escape }}"
  };
  const productList = [];
  let jsonResp, jsonRespArr, jsonRespArrStr;
  const numberOfProducts = 8;
  productList.push(productData);
  const currProductPageTitle = productData.productTitle;
  const productDataString = JSON.stringify(productList);
  const localData = localStorage.getItem("recentlyViewedProduct");
  if (localData === null) {
	localStorage.setItem("recentlyViewedProduct", productDataString);
  } else if (localData) {
	const oldProductData = localStorage.getItem("recentlyViewedProduct");
	const countProductData = (oldProductData.match(/productTitle/g) || []).length;
	const sameProduct = oldProductData.includes(currProductPageTitle);
	if (countProductData < numberOfProducts && sameProduct == false) {
	  jsonResp = JSON.parse(oldProductData);
	  jsonRespArr = jsonResp.concat(productList);
	  jsonRespArrStr = JSON.stringify(jsonRespArr);
	  localStorage.setItem("recentlyViewedProduct", jsonRespArrStr);
	} else if (countProductData >= numberOfProducts && sameProduct == false) {
	  jsonResp = JSON.parse(oldProductData);
	  jsonResp.shift();
	  jsonRespArr = jsonResp.concat(productList);
	  jsonRespArr = JSON.stringify(jsonRespArr);
	  localStorage.setItem("recentlyViewedProduct", jsonRespArr);
	}
  }
}
setRecentlyViewedProducts();
const localViewed = localStorage.recentlyViewedProduct;
function getRecentlyViewedProducts() {
  const productData = JSON.parse(localStorage.getItem("recentlyViewedProduct"));
  const recentlyViewedHtml = [];
  productData.map(item => {
	recentlyViewedHtml.unshift(`
	<li class="recently-viewed-grid-item">
	  <a href="${item.productUrl}"> 
		<img class="recently-viewed-img" src='${item.productImg}' loading="lazy" alt="${item.productImageAltText}" data-sndimg="${item.productImgsnd}"/>
	  </a>
	   <h3><a class="recently-viewed-a" href="${item.productUrl}">${item.productTitle}</a></h3>
	   <p>${item.productPrice}</p>
	</li>
   `);
  });
  const newProductData = `${recentlyViewedHtml.join("")}`;
  const fullContent = document.getElementsByClassName("recently-viewed-grid");
  fullContent[0].innerHTML = newProductData;
}
document.addEventListener("DOMContentLoaded", function (event) {
  getRecentlyViewedProducts();
});
</script>
コード解説
商品データの準備とローカルストレージへの保存
function setRecentlyViewedProducts() {
  const title = "{{ product.title }}".trim(); 
  if (!title) {
	return;
  }
・余分な空白を削除(trim())し、もしタイトルが空文字の場合は処理を中断しています。つまり、無効な商品情報の場合は保存しません。
商品情報の作成
現在の商品に関する情報(タイトル、画像 URL、サブ画像、価格、商品ページの URL、画像の代替テキスト)をオブジェクトとしてまとめています。
const productData = {
	productTitle: "{{ product.title }}",
	productImg: "{{ product.featured_media | img_url: '800x' }}",
	productImgsnd: "{%- if product.images[1] != blank -%}{{- product.images[1] | img_url: '800x' -}}{%- else -%}{{- product.featured_media | img_url: '800x' -}}{%- endif -%}",
	productPrice: "{{ product.price | money }}",
	productUrl: "{{ product.url }}",
	productImageAltText: "{{product.featured_media.alt | escape }}"
  };
ローカルストレージへ保存
・productList という配列を作成し、今回の productData を追加しています。
	・numberOfProducts は保持する商品の上限(ここでは 8 件)を指定しています。
	・localStorage.getItem(“recentlyViewedProduct”) によって、すでに保存されている「最近チェックした商品」の情報を取得します。
const productList = [];
  const numberOfProducts = 8;
  productList.push(productData);
  const currProductPageTitle = productData.productTitle;
  const productDataString = JSON.stringify(productList);
  const localData = localStorage.getItem("recentlyViewedProduct");
ローカルストレージに商品のデータを追加・更新する処理
もしローカルストレージにまだ「recentlyViewedProduct」が存在しない場合は、新しく保存します。また、閲覧した商品データを上限まで収集するようにし、上限以後は更新される形となります。これにより、最新の商品情報が表示されるようにしています。
  if (localData === null) {
	localStorage.setItem("recentlyViewedProduct", productDataString);
  } else if (localData) {
	const oldProductData = localStorage.getItem("recentlyViewedProduct");
	const countProductData = (oldProductData.match(/productTitle/g) || []).length;
	const sameProduct = oldProductData.includes(currProductPageTitle);
	if (countProductData < numberOfProducts && sameProduct == false) {
	  jsonResp = JSON.parse(oldProductData);
	  jsonRespArr = jsonResp.concat(productList);
	  jsonRespArrStr = JSON.stringify(jsonRespArr);
	  localStorage.setItem("recentlyViewedProduct", jsonRespArrStr);
	} else if (countProductData >= numberOfProducts && sameProduct == false) {
	  jsonResp = JSON.parse(oldProductData);
	  jsonResp.shift();
	  jsonRespArr = jsonResp.concat(productList);
	  jsonRespArr = JSON.stringify(jsonRespArr);
	  localStorage.setItem("recentlyViewedProduct", jsonRespArr);
	}
  }
}
保存されたデータの取得と表示
ローカルストレージから「recentlyViewedProduct」を取得し、各商品について、HTML のリストアイテムのテンプレート文字列を作成しています。
配置箇所は、class “recently-viewed-grid” を持つ要素の innerHTML に設定することで、画面上に一覧が表示されます。
function getRecentlyViewedProducts() {
  const productData = JSON.parse(localStorage.getItem("recentlyViewedProduct"));
  const recentlyViewedHtml = [];
  productData.map(item => {
	recentlyViewedHtml.unshift(`
	<li class="recently-viewed-grid-item">
	  <a href="${item.productUrl}"> 
		<img class="recently-viewed-img" src='${item.productImg}' loading="lazy" alt="${item.productImageAltText}" data-sndimg="${item.productImgsnd}"/>
	  </a>
	   <h3><a class="recently-viewed-a" href="${item.productUrl}">${item.productTitle}</a></h3>
	   <p>${item.productPrice}</p>
	</li>
   `);
  });
  const newProductData = `${recentlyViewedHtml.join("")}`;
  const fullContent = document.getElementsByClassName("recently-viewed-grid");
  fullContent[0].innerHTML = newProductData;
}
ページ読み込み時の処理
ページが完全に読み込まれた後でローカルストレージに保存されている「最近チェックした商品」の一覧を表示します。
document.addEventListener("DOMContentLoaded", function (event) {
  getRecentlyViewedProducts();
});
推奨の追加調整
実際の使用時は、ページ内に<ul class="recently-viewed-grid"></ul>を設置して、そこに最近チェックした商品が表示されるように設置します。またドロワーでの表示との複合を念頭に、複数個所へ表示ができるようにJavaScriptのカスタマイズ行ったり、カーソルが乗った状態で2枚目の画像表示を行う等、追加のカスタマイズを行うことで、使用したテーマに沿った構築も可能です。
結果
Shopifyで自由な箇所に「最近チェックした商品」を配置することで、大手ECも行っている効果的な閲覧履歴の活用が可能となります。購入率にも直結する施策のため、実際に売上が向上するケースが非常に多く、弊社での作成時はご提案・導入の多い機能です。
お気軽にお問い合わせください
弊社ではECをスタートされる方から、大規模ECの安全なリニューアル、個別のカスタマイズ実装まで幅広く対応可能です。
ご相談がございましたら、お気軽にご連絡ください。