今回はShopifyを使用して車両パーツを販売しているクライアントのために、カスタマイズ可能な車両選択機能の実装をしました。
Shopifyのアプリストアには同様の機能を提供するアプリが存在していましたが、カスタマイズ性と毎月の使用料に関する制約があり、テーマファイルの編集とプロダクトデータを利用し、この機能を実装することにしました。
実装の背景とプロセス
プロジェクトの主な課題は、既存の商品データを使用し、ユーザーが選択した車両に基づいて、対応するパーツのみを表示すること。
JavaScriptとクッキーデータを使用し、ユーザーが選択した車両を記憶し、適切なパーツを表示するシステムを実装。
さらに、対応しないパーツには注意書きを表示する機能も実装しました。
プロダクトタグに既に対応する車両データが入力されていたので、そのデータを使用し効率的な実装が可能となりました。
画像: Shopify Product Tagの例
特徴と成果
クライアントのサイトでは対象車両が十種以下と限定されていたため、実装は比較的簡易的で済みました。
この新機能により、ユーザーは自分の車両に適合するパーツを簡単に見つけることができるようになりました。
また、アプリを使用しないことでサイトへの負担を軽減し、余計なマンスリーフィーも発生せず、クライアントはこのソリューションに大変満足いただけました。
画像: 車両選択機能の実際の画面
コード例
それぞれのコードの配置場所やコードの詳細はThemeにより適宣変更してください。
インストールのご依頼も受け付けております。
snippets/car-selector.liquid
<div class="selector-tabs">
<div class="tabs">
<div class="tab-header">
<input id="メーカー" type="radio" name="tab_item" checked>
<label class="tab_item" for="メーカー">メーカー</label>
</div>
</div>
<div class="tab_content opener-active" id="メーカー_content">
<a class="vehicle_trigger" data-vehicle-type="車両名">
<img src="{{ '車両名.jpg' | asset_url }}">
<span class="text_cta">車両名</span>
</a>
</div>
snippets/car-selector.js
jQuery(document).ready(function ($) {
$("#opener").change(function () {
if ($(this).is(":checked")) {
$(".selector-wrapper").addClass("opener-active");
$(".selector-tabs").addClass("opener-active");
} else {
$(".selector-wrapper").removeClass("opener-active");
$(".selector-tabs").removeClass("opener-active");
}
});
$('input[name="tab_item"]').change(function () {
// 全てのタブコンテンツからクラスを削除
$(".tab_content").removeClass("opener-active");
// 選択されたタブに応じて対応するコンテンツにクラスを付与
if ($("#jeep").is(":checked")) {
$("#jeep_content").addClass("opener-active");
} else if ($("#toyota").is(":checked")) {
$("#toyota_content").addClass("opener-active");
} else if ($("#ford").is(":checked")) {
$("#ford_content").addClass("opener-active");
}
});
const SELECTED_VEHICLE_COOKIE = "selected_vehicle";
function updateFitMessage() {
const selectedVehicle = Cookies.get(SELECTED_VEHICLE_COOKIE);
if (selectedVehicle) {
const vehicleTag = "車種_" + selectedVehicle;
const tags = $("#fit-message").data("tags").split(",");
const message =
tags.includes(vehicleTag) || tags.includes("車種_全車種対応")
? `こちらの商品は${selectedVehicle}に<span class='fit-text'>対応</span>いたします。<br>*オプションにより異なります。`
: `こちらの商品は${selectedVehicle}には<span class='not-fit-text'>対応</span>いたしません。`;
$("#fit-message").addClass("has-message").html(message);
}
}
function toggleClearButton() {
Cookies.get(SELECTED_VEHICLE_COOKIE)
? $("#clear-button").show()
: $("#clear-button").hide();
}
function updateVehicleTriggers() {
const selectedVehicle = Cookies.get(SELECTED_VEHICLE_COOKIE);
$(".vehicle_trigger").each(function () {
const trigger = $(this);
const vehicleType = trigger.data("vehicle-type");
trigger.toggleClass("active", selectedVehicle === vehicleType);
});
}
function updateVehicleLabel() {
const selectedVehicle = Cookies.get(SELECTED_VEHICLE_COOKIE);
const label = $(".selector-header div");
if (selectedVehicle) {
const vehicleLink = `<a class='' href="/pages/parts-list-by-category">${selectedVehicle}</a>`;
label.html(vehicleLink);
} else {
label.text("あなたにあった商品を表示");
}
}
function updateCollectionLinks(vehicleType) {
const vehicleTypeSlug = vehicleType.toLowerCase().replace(/ /g, "-");
const vehicleTriggers = $(".vehicle_trigger")
.map(function () {
return $(this).data("vehicle-type").toLowerCase().replace(/ /g, "-");
})
.get();
$("a").each(function () {
const link = $(this);
const href = link.attr("href");
if (href) {
// hrefがundefinedまたはnullでないことを確認
// "/collections/"が含まれ、"/products/"が含まれないリンクを対象にする
if (href.includes("/collections/") && !href.includes("/products/")) {
if (
!vehicleTriggers.some(
(vt) => href.includes(vt) && vt !== vehicleTypeSlug
)
) {
const newHref = href.includes("vendor")
? `${href}&constraint=車種_${vehicleTypeSlug}`
: `${href}/車種_${vehicleTypeSlug}/`;
link.attr("href", newHref);
}
}
}
});
}
$(".vehicle_trigger").on("click", function () {
const vehicleType = $(this).data("vehicle-type");
Cookies.set(SELECTED_VEHICLE_COOKIE, vehicleType, { expires: 365 });
toggleClearButton();
updateVehicleTriggers();
updateVehicleLabel();
updateCollectionLinks(vehicleType);
const currentUrl = window.location.href;
if (
!currentUrl.includes("/products/") &&
!currentUrl.includes("/collections/")
) {
if (vehicleType.toLowerCase().replace(/ /g, "-")) {
window.location.href = "/pages/parts-list-by-category";
}
} else if (currentUrl.includes("/products/")) {
updateFitMessage();
}
});
$("#clear-button").on("click", function () {
Cookies.remove(SELECTED_VEHICLE_COOKIE);
toggleClearButton();
updateVehicleTriggers();
updateVehicleLabel();
});
function checkAndUpdateURLFromCookie() {
const selectedVehicle = Cookies.get(SELECTED_VEHICLE_COOKIE);
if (selectedVehicle) {
updateCollectionLinks(selectedVehicle);
}
}
// Initial setup
toggleClearButton();
updateVehicleTriggers();
updateVehicleLabel();
checkAndUpdateURLFromCookie();
if (window.location.href.includes("/products/")) {
updateFitMessage();
}
});
まとめ
このプロジェクトでは、既存のリソースを活用し、ユーザー体験を大幅に向上させることができた顕著な例です。
カスタマーのニーズに合わせたカスタマイズは、オンラインショッピングに不可欠な要素であり、E.N. Productionsでは様々な方法で最適な解決策を提案いたします。