Skip to main content
Version: next

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.

info

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:

my-extension/index.ts
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.

theme/modules/CustomMethod/CustomMethod.jsx
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 using SubmitShippingMethod in your component. This should always be true as false 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 a key and value 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);
    },
    });