Pourquoi nous avons migré notre checkout Shopify des hacks Liquid vers Checkout Extensibility

La bombe à retardement du checkout
Pendant trois ans, notre checkout Shopify Plus a fonctionné sur un patchwork fragile de overrides checkout.liquid, de scripts tiers et de Shopify Scripts que personne ne voulait posséder. Le checkout avait l'air sur mesure, mais l'implémentation était un passif. Chaque mise à jour Shopify signifiait une revue de diff d'une demi-journée. Chaque nouveau moyen de paiement nécessitait de retester l'ensemble du funnel. Et quand Shopify a annoncé la suppression des personnalisations checkout.liquid pour les pages Information, Livraison et Paiement, nous avions une deadline inflexible.
Nous avions deux options : persévérer avec l'approche legacy et lutter contre la plateforme, ou traiter Checkout Extensibility comme un problème d'architecture de premier plan. Nous avons choisi la seconde. La migration a pris six semaines, supprimé 2 400 lignes de Liquid et de JavaScript, et nous a donné un checkout plus rapide, plus testable et plus facile à étendre.
Ce que checkout.liquid nous a coûté
Le checkout est la page à plus fort impact de toute boutique en ligne. Une seconde de ralentissement peut faire chuter la conversion de plusieurs points de pourcentage. Notre fichier checkout.liquid était devenu un monolithe contrôlant le layout, le tracking, les vérifications anti-fraude, les upsells et la validation des champs personnalisés. Le problème n'était pas sa taille, mais son incontrolabilité.
Nous n'avions aucune séparation propre entre présentation et logique métier. Les tests A/B étaient implémentés en rendant conditionnellement des balises script selon les attributs du panier. Les badges de confiance étaient injectés par manipulation du DOM, ce qui cassait chaque fois que Shopify changeait des noms de classes. Et comme le fichier était partagé entre marchés, une modification pour une région risquait des régressions partout.
Pire, checkout.liquid s'exécute de manière synchrone à chaque étape du checkout. Ajouter un script qui bloquait le rendu ralentissait chaque acheteur, pas seulement ceux qui avaient besoin de la fonctionnalité. Nous avions optimisé le frontend ailleurs, mais le checkout était notre angle mort.
Ce que change Checkout Extensibility
Shopify Checkout Extensibility remplace le template monolithique par un modèle de composition. Au lieu d'un seul fichier qui possède tout, on construit le checkout à partir de trois primitives :
- Checkout UI Extensions pour rendre des composants React personnalisés dans le checkout Shopify.
- Web Pixels et Customer Events pour le tracking et l'analytics.
- Functions pour la validation côté serveur et la logique de prix qui s'exécute dans l'infrastructure Shopify.
L'architecture est pilotée par les événements et scopeée. Une UI extension ne charge que sur l'étape où elle est nécessaire. Une Function ne s'exécute que lorsque sa condition spécifique est remplie. Et tout est versionné, type-safe et déployable via l'infrastructure Shopify.
La stratégie de migration
Nous n'avons pas tenté de réécriture en mode big bang. Le risque de casser le checkout d'un store en production est trop élevé. Au lieu de cela, nous avons fait tourner les anciens et nouveaux systèmes en parallèle, en migrant un sujet à la fois.
Étape 1 : Inventaire de la surface legacy
Nous avons audité chaque ligne de checkout.liquid et l'avons classée dans l'un des quatre buckets :
- Modifications UI pouvant devenir des Checkout UI Extensions.
- Tracking et analytics devant migrer vers les Web Pixels.
- Règles de prix et de validation appartenant aux Shopify Functions.
- Code mort pouvant simplement être supprimé.
Environ trente pour cent du fichier sont tombés dans la dernière catégorie. Cela seul a justifié l'audit.
Étape 2 : Construire le scaffold d'extensions
Nous avons créé une seule app Shopify propriétaire de toutes les extensions de checkout du store. Chaque extension vivait dans son propre répertoire avec ses propres tests. Le code partagé, comme les clients API et les helpers de validation, vivait dans un package workspace pour que les extensions ne puissent pas dépendre accidentellement les unes des autres.
// extensions/checkout-upsell/src/CheckoutUpsell.tsx
import { useExtensionApi, TextBlock, Button } from '@shopify/checkout-ui-extensions-react';
export default function CheckoutUpsell() {
const { extension, lines, applyMetafieldsChange } = useExtensionApi();
const { appMetafields } = extension;
async function addRecommendedVariant(variantId: string) {
await applyMetafieldsChange({
type: 'updateMetafield',
namespace: 'checkout_upsell',
key: 'selected_variant',
value: variantId,
valueType: 'string',
});
}
return (
<TextBlock>Complete your kit with a matching item</TextBlock>
// Render dynamic recommendation based on cart lines
);
}Étape 3 : Déplacer la logique métier dans les Functions
La validation côté serveur était la partie la plus effrayante à migrer car un bug pouvait silencieusement casser les prix. Nous avons commencé par une règle de remise simple basée sur des metafields et ajouté de l'observabilité avant de monter en charge.
// extensions/cart-validation/src/run.rs
use shopify_function::prelude::*;
use serde::Serialize;
#[derive(Serialize)]
struct Output {
discount_application_strategy: String,
}
#[shopify_function_target
query = "src/run.graphql"]
fn run(input: ResponseData) -> Result<Output> {
let eligible = input.cart.lines.iter().all(|line| {
line.merchandise.as_ref().map_or(false, |m| {
matches!(m.product.is_gift_card, Some(false))
})
});
Ok(Output {
discount_application_strategy: if eligible { "FIRST".to_string() } else { "ALL".to_string() },
})
}Étape 4 : Validation parallèle et bascule
Pendant deux semaines, nous avons journalisé la sortie des nouvelles Functions et UI Extensions à côté du comportement legacy. Toute divergence déclenchait une alerte. Une fois que le taux de divergence est resté à zéro pendant soixante-douze heures, nous avons désactivé le code legacy pour les fonctionnalités migrées.
Ce qui a cassé et comment nous l'avons réparé
La première chose à casser a été notre framework de tests A/B. Il reposait sur l'injection de scripts différents selon les attributs du checkout. Sans checkout.liquid, nous avons dû reconstruire l'attribution d'expérience sous forme de Web Pixel déclenché au début du checkout et poussant la variante dans les Customer Events. C'était plus de travail au départ, mais la qualité des données s'est améliorée car les événements n'étaient plus perdus quand les scripts ne chargeaient pas.
La deuxième surprise a été la performance. Nous nous attendions à un checkout plus rapide, mais nous avons sous-estimé de combien. Retirer les scripts tiers bloquants du chemin critique a réduit notre Largest Contentful Paint sur l'étape de paiement de près de quarante pour cent. Les extensions React sont lazy-loaded et sandboxées, elles ne peuvent donc pas bloquer le rendu du core checkout Shopify.
Le troisième problème était organisationnel. Checkout Extensibility nous a forcés à séparer proprement la logique frontend et backend. Les designers ne pouvaient plus simplement lancer une balise script dans un template et considérer que c'était terminé. Ils devaient penser en termes d'extensions scopées et de tracking piloté par les événements. Cette friction était intentionnelle et a amélioré la qualité des nouvelles fonctionnalités de checkout.
Takeaways
Traiter le checkout comme une extension de plateforme plutôt qu'un override de template change la façon dont on conçoit, teste et déploie les modifications. La migration n'est pas qu'un refactoring ; c'est un mouvement architectural.
Commencez par un inventaire et classifiez chaque personnalisation legacy. Faites tourner les anciens et nouveaux systèmes en parallèle avec du trafic réel avant de basculer. Déplacez la logique métier dans les Functions, la logique de présentation dans les UI Extensions et le tracking dans les Web Pixels. Attendez-vous à ce que certains outils A/B et analytics doivent être reconstruits. Le gain est un checkout plus rapide, plus sûr et aligné avec la roadmap Shopify plutôt que contre elle.

Écrit par
Miracle Kalu
Senior Full Stack Engineer
Vous avez aimé cet article ?
Je suis disponible pour des rôles d'ingénierie senior et du conseil technique. Parlons-en.
Prendre contact →Publié le 13 juin 2026 · 5 min de lecture
Continuer la lecture
