[予約]Shopifyでの商品ごとに異なる発送予定日を注文情報に出力する方法(開発者向け)

by keigo matsunari

予約注文などで商品ごとに異なる発送予定日の情報を持たせて、カートの中の商品発送予定日を比較して一番遅いものを注文のAttributesとして出力するアイデアと注意点を紹介します!
※こちらは開発者向けの内容となります。

予約カスタマイズアプローチ

予約商品と通常商品が同時購入された場合は予約商品に合わせて、まとめて発送する

・予約商品と通常商品は同時購入させない

・予約商品と通常商品が同時購入された場合は、別々に発送処理を行う(20223/07月のアップデートで可能になりました)


今回1つ目のアプローチについて説明します。

なぜこのようなカスタマイズが必要になるかというと、ShopifyがOrderを分割できなかったためです。 20223/07月のアップデートで同じ注文内の商品を別々にフルフィルメント処理できるようになりました。 これにより、このようなカスタマイズが必要になるパターンは少なくなると思います。 ただ、別々に発送する場合は送料が異なってきますので従来通り予約と通常商品と同時購入した時はまとめて発送したい場合はこちらのカスタマイズを参考にしてみてください。

具体例

例えばカートに3つの異なる発送予定日を持った商品があります。

 Product A - Estimated shipping date: 2025-01-05 

Product B - Estimated shipping date: 2025-01-16 

Product C - Estimated shipping date: 2025-01-12


この場合はProduct Bの発送予定日が一番遅いので、注文全体の発送予定日を2025-01-16にするようにします。
注文の付与情報(Attributes)はThank youページ、注文状況ページ、マイページ、注文確認メールにカスタマイズで表示することができます。
発送予定日をネクストエンジンなどで配送会社に自動連携している場合では、予約の発送予定日を連携することが可能です。

実装方法アイデア紹介

商品ごとに異なる発送予定日は、商品のメタフィールド日付型で用意する。 
予約商品がカートにある場合は、発送予定日を比較するコードをカスタムする。 

- テーマによって、liquidのみで実装可能なパターンとJSが必要になるパターンがあります。テーマやサードパティーのアプリにより実装内容は変わりますのであくまで参考にしてください。

liquidのみで実装可能パターン Cartで数量変更された際に、リロードが走りliquidコードが再initializeされる場合 liquidのみで素直にデータがパスできるかはケースバイケースなので検証が必要です。こちらのが比較的シンプルな実装です。

cart.liquid

{% liquid
	assign latestEstimatedShipDate = 'today' | date: '%s'
	assign isPreorderInCart = false

	for item in cart.items
		if item.product.tags contains 'pre-order'
			assign isPreorderInCart = true
			assign curretItemDeliverDate = item.product.metafields.preorder.deliver-date | date: '%s'
			if latestEstimatedShipDate < curretItemDeliverDate and item.product.metafields.preorder.deliver-date != blank
				assign latestEstimatedShipDate = curretItemDeliverDate
			endif
		endif
	endfor
%}

{% if isPreorderInCart %}
	<p class="cart-attribute__field">
	  <label for="pre-order-deliver-date">Pre-order-deliver-date</label>
	  <input id="pre-order-deliver-date" type="text" name="attributes[Pre-order-deliver-date]" value="{{ latestEstimatedShipDate | date: '%Y-%m-%d' }}">
	</p>
{% endif %}

JSが必要なパターン Ajax apiのエンドポイントcart/update.js を使用します。 注意点. 数量変更のたびにcart.jsからfetchしてもcart.jsのレスポンスにメタフィールド情報が含まれないので、DOMのattributeから持ってくるなどの工夫が必要です

コードタイトル


function getLatestShippingDate(cartPreOrderItems) {
	let latestEstimatedShippingDate = new Date().getTime();
	for (const item of cartPreOrderItems) {
		if (latestEstimatedShippingDate < new Date(item.shippingDate).getTime()) {
			latestEstimatedShippingDate = new Date(item.shippingDate).getTime();
		}
	}
	return new Date(latestEstimatedShippingDate);
}

function updateShippingDateAttribute(shippingDate) {
  
  const formData = JSON.stringify({
    attributes: {
      'Pre-order-deliver-date': shippingDate,
    }
  });

  fetch('cart/update.js', {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: formData
  })
  .then((response) => {
    if (!response.ok) {
      throw new Error('Network response was not ok');
    }
    return response.json();
  })
  .catch((error) => {
    console.error('Fetch error:', error);
  });
}

const cartPreOrderItems = document.querySelectorAll(".pre-order").getAttribute('deliveryDate');
updateShippingDateAttribute(getLatestShippingDate(cartPreOrderItems));

予約商品のカスタマイズアプローチと具体的な実装アイデアを紹介しました。 これらを応用して、予約商品がある時は発送日時指定アプリでの発送日時を指定不可にして、予約の発送日時に置き換える。同時購入時の発送を同時にするか別々にするかをお客さんに指定させるなど要件次第では色々と応用可能です。

この著者の記事一覧

EC構築から広告運用までワンストップで提供。

資料請求 お問い合わせ