Use custom shipping information
Since version 3.10
Learn how to implement custom shipping methods that require additional information from customers during checkout. While most shipping methods are straightforward, some specialized options like pickup points need extra details before order completion. This guide walks through implementing custom shipping methods with additional input fields, form validation, and data handling in your Front-Commerce storefront.
The method described in this guide is using the shippingMethodAdditionalData
feature from ExtensionComponentMap
to register a new component, which was
introduced in Front-Commerce v3.10.0. If you are using an older version, you
should use the legacy method described in the
v2 documentation.
Before tackling this documentation, please make sure that you've understood the essentials of Front-Commerce and that you've registered a shipping method in your backend (Magento2…).
All the code that will be created in this page should be put in a specific
extension for the shipping method. If you create a specific one, please keep in
mind that you need to register it in front-commerce.config.ts
.
Identify your shipping method
If your shipping method is correctly registered in your backend, the following GraphQL query should return your method's codes.
{
checkout {
availableShippingMethodList(
address: { country_id: "FR", postcode: "31400" }
) {
data {
carrier_code
method_code
}
}
}
}
Make sure to use an address that is eligible for your shipping method.
Display a custom input in your shipping method
Once you've done this request, you will be able to get the method_code
of your
shipping method. You should use those to register a new component by registering
it through the
ExtensionComponentMap
:
import { defineExtension } from "@front-commerce/core";
export default defineExtension({
name: "myShippingMethodExtension",
meta: import.meta,
unstable_lifecycleHooks: {
onFeaturesInit: (hooks) => {
hooks.registerFeature("shippingMethodAdditionalData", {
ui: {
componentsMap: {
"<method_code>": new URL(
"theme/modules/CustomMethod/CustomMethod.jsx",
import.meta.url
),
},
},
});
},
},
});
The custom component referenced here should display the additional information of your shipping method to the user.
import React, { useState } from "react";
import SubmitShippingMethod from "theme/modules/Checkout/ShippingMethod/SubmitShippingMethod/SubmitShippingMethod";
const CustomMethod = ({ pending, error, submitAdditionalData }) => {
const [customValue, setCustomValue] = useState();
return (
<div className="custom-shipping-method">
<input
onChange={(event) => setCustomValue(event.target.value)}
value={customValue}
name="customValue"
type="text"
/>
<SubmitShippingMethod
key="submit"
state={pending ? "pending" : error ? "disabled" : undefined}
error={error}
onSubmit={() => {
submitAdditionalData([{ key: "customValue", value: customValue }]);
}}
/>
</div>
);
};
CustomMethod.handlesNextStepButton = () => true;
CustomMethod.AddressRecapLine = (props) => (
<div>
You can change how the address is displayed in the Address Recap of the
checkout by declaring this component.
</div>
);
export default CustomMethod;
Things to understand here:
- The
SubmitShippingMethod
component is a common component across all shipping methods to ensure consistency in how methods are managed. CustomMethod.handlesNextStepButton = () => true;
means that you are indeed usingSubmitShippingMethod
in your component. This should always betrue
asfalse
is the legacy behavior.CustomMethod.AddressRecapLine
(optional) is used to change how the shipping address is displayed in the checkout recap once you've selected your custom shipping method. For instance this is what you will use to display a pickup address instead of the shipping address filled by the user.submitAdditionalData
sends an array of objects with akey
andvalue
to your backend. This means that when the shipping method will be set, the additional data will be sent to your backend at the same time. We'll see in the next section how to act on them.
In this example we're only setting a text input, but you can do fancier things
like fetching a list of pickup points from GraphQL and displaying them here. To
do so, you need to use <PostalAddressSelector />
component that allows to
select a pickup. See
Add a shipping method with pickup points
documentation for more information.
Send the additional data to your backend
Once you've registered a shipping method with additional data, the
setCheckoutShippingInformation
mutation will be sent to Front-Commerce.
Front-Commerce will then send the additional data provided in this mutation to
your backend.
For instance, in Magento1, it'll be passed to the API at
/api/rest/frontcommerce/cart/mine/shipping-information
by sending a JSON
looking like this:
{
"shipping_carrier_code": "mondialrelaypickup",
"shipping_method_code": "24R",
"additional_data": [
{
"key": "customValue",
"value": "custom"
}
]
}
This means that you have two solutions to act upon these values in your backend:
-
you can either override the API in your backend (recommended way) by registering an observer (
frontcommerce_api_set_shipping_information_before_save
in Magento1's case) -
or you can trigger a function in your GraphQL module before calling the backend's API by using the following method:
loaders.ShippingMethod.registerShipmentMethodsHandler({
method: "<carrier_code>_<method_code>",
updateShippingInformation: (shippingMethod, data) => {
// By registering this method, this means that you can transform the data or send a different request before calling the backend's API.
// The resolved data here will be the data sent to your backend in the base API
return Promise.resolve(data);
},
});