Scripts Deadline: Migrer vers Functions d'ici le 30 juin 2026

Scripts Deadline: Migrer vers Functions d'ici le 30 juin 2026

Scripts Deadline: Migrer vers Functions d'ici le 30 juin 2026

Date limite Shopify Scripts : Migrer vers Functions d'ici le 30 juin | Blog Revize

Nous sommes le 16 avril 2026. Hier, le 15 avril, Shopify a verrouillé définitivement le Script Editor. Vous ne pouvez plus créer ni publier de nouveau Script. Cette échéance est particulièrement critique pour la logique post-achat : les modifications d'adresse de livraison représentent la modification post-achat numéro 1, comptant pour 30.2 % de toutes les commandes modifiées (Revize, 2026), et tout Script gérant encore ces modifications est désormais figé. L'arrêt complet de l'exécution intervient dans 75 jours, le 30 juin 2026.

Si vous êtes un développeur Shopify Plus — ou l'agence gérant une boutique Plus — et que vous avez repoussé cette migration au « prochain sprint » ces douze derniers mois, vous avez un problème. Pas un problème secondaire. Un problème du type « votre passage à la caisse plante à minuit le 1er juillet ». La plupart des boutiques Plus ont accumulé entre 5 et 20 Scripts au fil des ans, chacun gérant discrètement une règle de remise, un masquage de livraison ou une passerelle de paiement que personne ne se rappelle avoir codé.

Ce guide est le manuel de migration technique que nous aurions aimé avoir en janvier. Il traite du code réel — pas seulement de la stratégie. À la fin de votre lecture, vous saurez comment structurer une Function avec la Shopify CLI, écrire la logique en Rust ou JavaScript pour les remises, les personnalisations de livraison et de paiement, la tester en toute sécurité sur un sous-ensemble ciblé de vos clients, et la déployer en production sans perturber votre processus d'achat actuel.

Retirons les Scripts de votre boutique et installons les Functions.



Developer migrating Shopify Scripts to Shopify Functions modules

Réponse rapide : Scripts → Functions en 60 secondes

La migration en un paragraphe : Les Shopify Scripts (code Ruby dans le Script Editor, réservés à Plus) sont remplacés par les Shopify Functions (modules WebAssembly écrits en Rust ou JavaScript, disponibles pour tous les forfaits). Vous générez une Function avec shopify app generate extension, écrivez une requête run.graphql qui récupère les données de panier nécessaires, écrivez un fichier run.rs ou run.js qui renvoie les opérations (remises, modes de livraison masqués, etc.), puis déployez avec shopify app deploy et l'activez via l'Admin ou une mutation GraphQL. Les Functions s'exécutent sous forme de WASM compilé avec une latence inférieure à 5 ms, fonctionnent sur tous les forfaits et constituent la seule méthode de personnalisation prise en charge par Shopify à l'avenir.

Ce qui change réellement le 30 juin

Avant de toucher au code, clarifions les dates. Il y en a deux, et les deux sont cruciales.


Date

Ce qui se passe

Votre action

15 avril 2026 (passé)

Script Editor en lecture seule. Aucun nouveau Script. Aucune modification des Scripts existants.

Les Scripts existants s'exécutent encore. Migrez maintenant ou figez votre logique.

30 juin 2026

Tous les Shopify Scripts cessent de s'exécuter. Définitivement.

Votre Function de remplacement doit être active avant cette date.

La migration est binaire. Soit votre Function est déployée d'ici le 30 juin et votre passage à la caisse continue de fonctionner, soit elle ne l'est pas — et chaque panier concerné revient silencieusement aux tarifs standards, aux modes de livraison par défaut et à l'activation de toutes les méthodes de paiement. Pas de demi-mesure. Le Script s'exécute ou ne s'exécute pas, et après le 30 juin, il ne s'exécute plus.

Conseil : Allez dans Settings → Checkout → Customizations Report dans votre admin Shopify. Vous y trouverez la liste de tous les Scripts actifs sur votre boutique, leur rôle et le type de Function de remplacement recommandé. Commencez par là.

Functions vs Scripts : Ce qui a changé


Dimension

Shopify Scripts (obsolète)

Shopify Functions (remplacement)

Langage

Ruby DSL (spécifique à Shopify)

Rust, JavaScript, TypeScript

Runtime

Ruby sandboxé sur l'infra Shopify

WebAssembly (WASM) — exécution < 5 ms

Disponibilité forfait

Plus uniquement

Tous les forfaits (les applications personnalisées nécessitent Plus ; les applications publiques sont ouvertes)

Éditeur

Script Editor dans l'admin

IDE local + Shopify CLI

Contrôle de version

Aucun — modifications en direct

Compatible Git — contrôle de version complet

Tests

Manuels dans le processus d'achat

Développement local avec shopify app dev, liens de prévisualisation

Déploiement

Clic sur « Enregistrer » dans l'admin

shopify app deploy depuis le terminal

Cibles

Articles, livraison, paiements

Remises, Cart Transform, Validation, Delivery Customization, Payment Customization, Order Routing, Fulfillment Constraints, et plus

Le changement d'architecture est majeur. Les Scripts consistaient à « modifier du Ruby dans une zone de texte ». Les Functions consistent à « écrire une véritable application, la soumettre au contrôle de version, la tester localement, la déployer via un vrai pipeline CI ». La courbe d'apprentissage est plus raide. C'est aussi la dernière migration de logique de paiement que vous ferez à moyen terme — les Functions représentent l'engagement à long terme de Shopify, pas une solution temporaire comme l'ont été les Scripts.

Associer vos Scripts au bon type de Function

Chaque Script actuel correspond à une API de Function spécifique. Voici le tableau de correspondance à garder sous les yeux.


Ancien type de Script

Rôle

Nouvelle API de Function

Cible de la Function

Line Item Script

Appliquer des remises à des produits / clients / conditions de panier spécifiques

Cart & Checkout Discounts API

cart.lines.discounts.generate.run

Shipping Script (remise)

Livraison gratuite / remisée selon les règles du panier

Cart & Checkout Discounts API

cart.delivery-options.discounts.generate.run

Shipping Script (masquer / renommer / réordonner)

Masquer un tarif de livraison au-dessus de X $, renommer « Standard » en « Gratuit dès 50 $ »

Delivery Customization API

cart.delivery-options.transform.run

Payment Script

Masquer PayPal pour le B2B, masquer le paiement à la livraison au-dessus de 500 $, réordonner les méthodes

Payment Customization API

cart.payment-methods.transform.run

Script modifiant le panier (rare)

Regrouper des produits, remplacer des articles

Cart Transform API

cart.transform.run

Script de blocage de commande

Rejeter le panier si le mélange de SKU est invalide

Cart & Checkout Validation API

cart.validations.generate.run

Si vous avez dix Scripts, vous développerez probablement trois à cinq Functions — plusieurs Scripts se regroupent souvent en une seule Function dotée d'une logique d'embranchement plus propre.



Shopify Functions unifying discounts, delivery, and payment customizations

Prérequis : Configurer votre environnement de développement local

Avant de générer une Function, vous devez installer trois outils localement. Exécutez ces vérifications dans votre terminal.

1. Node.js 18+


node --version
# Doit être >= 18.0.0
node --version
# Doit être >= 18.0.0

Si la version est plus ancienne, installez-la via nvm ou téléchargez-la depuis nodejs.org.

2. Shopify CLI 3+


npm install -g @shopify/cli@latest
shopify version
# Doit afficher 3.x ou plus
npm install -g @shopify/cli@latest
shopify version
# Doit afficher 3.x ou plus

3. Toolchain Rust (uniquement si vous écrivez des Functions en Rust)


curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-wasip1
cargo --version
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-wasip1
cargo --version

Les Functions en JavaScript n'ont pas besoin de Rust. Choisissez un langage pour votre équipe et tenez-vous-y — mélanger les deux augmente la charge de maintenance.

4. Une boutique de développement

Connectez-vous à votre tableau de bord Partner et créez une nouvelle boutique de développement, ou utilisez-en une existante. Vous y déploirez les Functions avant de les passer en production.

Générer votre première Function

La CLI génère la majeure partie du code de base. Dans n'importe quel répertoire :


# Créer une nouvelle application Shopify (ignorer si vous en avez déjà une)
shopify app init my-checkout-functions
cd my-checkout-functions

# Générer une extension de type Function
shopify app generate extension
# Créer une nouvelle application Shopify (ignorer si vous en avez déjà une)
shopify app init my-checkout-functions
cd my-checkout-functions

# Générer une extension de type Function
shopify app generate extension

La CLI vous guide à travers les étapes. Pour une Function de remise, vous choisirez :

  • Type: Function

  • Template: discount (ou cart_checkout_validation, delivery_customization, payment_customization, etc.)

  • Language: Rust ou JavaScript

  • Name: quelque chose comme volume-discount-fn

Cela crée le répertoire extensions/volume-discount-fn/ contenant :


extensions/volume-discount-fn/
├── shopify.extension.toml      # Config de la Function cibles, build, version
├── src/
├── cart_lines_discounts_generate_run.graphql   # Requête d'entrée
└── cart_lines_discounts_generate_run.rs        # Logique de la Function
├── Cargo.toml                  # Dépendances Rust (Rust uniquement)
└── README.md
extensions/volume-discount-fn/
├── shopify.extension.toml      # Config de la Function cibles, build, version
├── src/
├── cart_lines_discounts_generate_run.graphql   # Requête d'entrée
└── cart_lines_discounts_generate_run.rs        # Logique de la Function
├── Cargo.toml                  # Dépendances Rust (Rust uniquement)
└── README.md

Les trois fichiers que vous modifierez constamment sont le .toml (config), le .graphql (entrée) et le .rs / .js (logique). C'est tout.

Tutoriel 1 : Remplacer un Line Item Script (Remise sur volume)

Supposons que votre ancien Script offrait 10 % de réduction sur le sous-total de la commande dès que le panier contenait au moins 5 articles d'une collection spécifique. Voici l'équivalent avec une Function.

Étape 1.1 : La configuration (shopify.extension.toml)


api_version = "2026-01"

[[extensions]]
name = "volume-discount-fn"
handle = "volume-discount-fn"
type = "function"

[[extensions.targeting]]
target = "cart.lines.discounts.generate.run"
input_query = "src/cart_lines_discounts_generate_run.graphql"
export = "cart_lines_discounts_generate_run"

[extensions.build]
command = "cargo build --target=wasm32-wasip1 --release"
path = "target/wasm32-wasip1/release/volume-discount-fn.wasm"
watch = ["src/**/*.rs"]
api_version = "2026-01"

[[extensions]]
name = "volume-discount-fn"
handle = "volume-discount-fn"
type = "function"

[[extensions.targeting]]
target = "cart.lines.discounts.generate.run"
input_query = "src/cart_lines_discounts_generate_run.graphql"
export = "cart_lines_discounts_generate_run"

[extensions.build]
command = "cargo build --target=wasm32-wasip1 --release"
path = "target/wasm32-wasip1/release/volume-discount-fn.wasm"
watch = ["src/**/*.rs"]

Étape 1.2 : La requête d'entrée (src/cart_lines_discounts_generate_run.graphql)


query Input {
  cart {
    lines {
      id
      quantity
      cost {
        subtotalAmount {
          amount
        }
      }
      merchandise {
        ... on ProductVariant {
          product {
            inAnyCollection(ids: ["gid://shopify/Collection/123456789"])
          }
        }
      }
    }
  }
  discount {
    discountClasses
  }
}
query Input {
  cart {
    lines {
      id
      quantity
      cost {
        subtotalAmount {
          amount
        }
      }
      merchandise {
        ... on ProductVariant {
          product {
            inAnyCollection(ids: ["gid://shopify/Collection/123456789"])
          }
        }
      }
    }
  }
  discount {
    discountClasses
  }
}

Conseil : Les Functions ne voient que les données que vous demandez. Gardez le GraphQL minimal — chaque champ omis permet une exécution plus rapide et moins coûteuse.

Étape 1.3 : La logique (src/cart_lines_discounts_generate_run.rs)


use super::schema;
use shopify_function::prelude::*;
use shopify_function::Result;

#[shopify_function]
fn cart_lines_discounts_generate_run(
    input: schema::cart_lines_discounts_generate_run::Input,
) -> Result<schema::CartLinesDiscountsGenerateRunResult> {
    // Sortie si la classe de remise ne correspond pas
    let has_order_discount = input
        .discount()
        .discount_classes()
        .contains(&schema::DiscountClass::Order);

    if !has_order_discount {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Somme des quantités d'articles de la collection cible
    let qualifying_qty: i64 = input
        .cart()
        .lines()
        .iter()
        .filter(|line| {
            if let schema::Merchandise::ProductVariant(v) = line.merchandise() {
                *v.product().in_any_collection()
            } else {
                false
            }
        })
        .map(|line| *line.quantity())
        .sum();

    if qualifying_qty < 5 {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Appliquer 10 % de réduction sur le sous-total de la commande
    Ok(schema::CartLinesDiscountsGenerateRunResult {
        operations: vec![schema::CartOperation::OrderDiscountsAdd(
            schema::OrderDiscountsAddOperation {
                selection_strategy: schema::OrderDiscountSelectionStrategy::First,
                candidates: vec![schema::OrderDiscountCandidate {
                    targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal(
                        schema::OrderSubtotalTarget {
                            excluded_cart_line_ids: vec![],
                        },
                    )],
                    message: Some("Volume discount: 10% off".to_string()),
                    value: schema::OrderDiscountCandidateValue::Percentage(
                        schema::Percentage { value: Decimal(10.0) }
                    ),
                    conditions: None,
                    associated_discount_code: None,
                }],
            },
        )],
    })
}
use super::schema;
use shopify_function::prelude::*;
use shopify_function::Result;

#[shopify_function]
fn cart_lines_discounts_generate_run(
    input: schema::cart_lines_discounts_generate_run::Input,
) -> Result<schema::CartLinesDiscountsGenerateRunResult> {
    // Sortie si la classe de remise ne correspond pas
    let has_order_discount = input
        .discount()
        .discount_classes()
        .contains(&schema::DiscountClass::Order);

    if !has_order_discount {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Somme des quantités d'articles de la collection cible
    let qualifying_qty: i64 = input
        .cart()
        .lines()
        .iter()
        .filter(|line| {
            if let schema::Merchandise::ProductVariant(v) = line.merchandise() {
                *v.product().in_any_collection()
            } else {
                false
            }
        })
        .map(|line| *line.quantity())
        .sum();

    if qualifying_qty < 5 {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Appliquer 10 % de réduction sur le sous-total de la commande
    Ok(schema::CartLinesDiscountsGenerateRunResult {
        operations: vec![schema::CartOperation::OrderDiscountsAdd(
            schema::OrderDiscountsAddOperation {
                selection_strategy: schema::OrderDiscountSelectionStrategy::First,
                candidates: vec![schema::OrderDiscountCandidate {
                    targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal(
                        schema::OrderSubtotalTarget {
                            excluded_cart_line_ids: vec![],
                        },
                    )],
                    message: Some("Volume discount: 10% off".to_string()),
                    value: schema::OrderDiscountCandidateValue::Percentage(
                        schema::Percentage { value: Decimal(10.0) }
                    ),
                    conditions: None,
                    associated_discount_code: None,
                }],
            },
        )],
    })
}

Étape 1.4 : Tester, déployer, activer


# Développement local avec rechargement à chaud
shopify app dev

# Une fois prêt, déployez
shopify app deploy

# Dans le panneau GraphiQL qui s'ouvre (appuyez sur `g` dans le terminal de dev),
# créez la remise automatique qui utilise votre Function :
# Développement local avec rechargement à chaud
shopify app dev

# Une fois prêt, déployez
shopify app deploy

# Dans le panneau GraphiQL qui s'ouvre (appuyez sur `g` dans le terminal de dev),
# créez la remise automatique qui utilise votre Function :
mutation {
  discountAutomaticAppCreate(
    automaticAppDiscount: {
      title: "Volume Discount (5+ collection items)"
      functionHandle: "volume-discount-fn"
      discountClasses: [ORDER]
      startsAt: "2026-04-16T00:00:00Z"
    }
  ) {
    automaticAppDiscount { discountId }
    userErrors { field message }
  }
}
mutation {
  discountAutomaticAppCreate(
    automaticAppDiscount: {
      title: "Volume Discount (5+ collection items)"
      functionHandle: "volume-discount-fn"
      discountClasses: [ORDER]
      startsAt: "2026-04-16T00:00:00Z"
    }
  ) {
    automaticAppDiscount { discountId }
    userErrors { field message }
  }
}

C'est tout. La Function est active, soumise au contrôle de version et remplace complètement l'ancien Script.

Tutoriel 2 : Remplacer un Shipping Script (Masquer une méthode au-dessus d'un seuil de panier)

Un Script classique : « Masquer la livraison Express lorsque le sous-total du panier dépasse 500 $ pour éviter des envois urgents coûteux sur de grosses commandes ». Voici la version Function de type Delivery Customization.

Étape 2.1 : Génération du code


shopify app generate extension --template delivery_customization --name hide-express-fn
shopify app generate extension --template delivery_customization --name hide-express-fn

Étape 2.2 : Requête d'entrée (src/run.graphql)


query Input {
  cart {
    cost {
      subtotalAmount {
        amount
      }
    }
    deliveryGroups {
      deliveryOptions {
        handle
        title
      }
    }
  }
}
query Input {
  cart {
    cost {
      subtotalAmount {
        amount
      }
    }
    deliveryGroups {
      deliveryOptions {
        handle
        title
      }
    }
  }
}

Étape 2.3 : Logique (src/run.js — variante JavaScript)


// @ts-check
/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

const NO_CHANGES = { operations: [] };
const THRESHOLD = 500.0;
const HIDE_TITLES = ["Express", "Overnight"];

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const subtotal = parseFloat(input.cart.cost.subtotalAmount.amount);
  if (subtotal < THRESHOLD) return NO_CHANGES;

  const operations = input.cart.deliveryGroups.flatMap((group) =>
    group.deliveryOptions
      .filter((opt) => HIDE_TITLES.some((t) => opt.title.includes(t)))
      .map((opt) => ({
        hide: { deliveryOptionHandle: opt.handle },
      }))
  );

  return { operations };
}
// @ts-check
/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

const NO_CHANGES = { operations: [] };
const THRESHOLD = 500.0;
const HIDE_TITLES = ["Express", "Overnight"];

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const subtotal = parseFloat(input.cart.cost.subtotalAmount.amount);
  if (subtotal < THRESHOLD) return NO_CHANGES;

  const operations = input.cart.deliveryGroups.flatMap((group) =>
    group.deliveryOptions
      .filter((opt) => HIDE_TITLES.some((t) => opt.title.includes(t)))
      .map((opt) => ({
        hide: { deliveryOptionHandle: opt.handle },
      }))
  );

  return { operations };
}

Étape 2.4 : Activation via l'Admin (aucune mutation GraphQL requise)

Les Delivery Customizations disposent d'une interface d'administration intégrée. Après shopify app deploy :

  1. Allez dans Settings → Shipping and delivery

  2. Faites défiler jusqu'à la section Customizations en bas

  3. Cliquez sur Add customization → sélectionnez votre Function

  4. Enregistrez

La règle de masquage est active en production. Aucune mutation requise.



Shopify delivery customization Function hiding shipping option at checkout

Tutoriel 3 : Remplacer un Payment Script (Masquer le paiement à la livraison pour le B2B)

Ancien Script : « Masquer le paiement à la livraison pour tout client ayant le tag 'B2B' ». Voici la version Payment Customization.

Étape 3.1 : Génération du code


shopify app generate extension --template payment_customization --name hide-cod-b2b-fn
shopify app generate extension --template payment_customization --name hide-cod-b2b-fn

Étape 3.2 : Requête d'entrée


query Input {
  cart {
    buyerIdentity {
      customer {
        hasTags(tags: [{ tag: "B2B" }]) {
          tag
          hasTag
        }
      }
    }
  }
  paymentMethods {
    id
    name
  }
}
query Input {
  cart {
    buyerIdentity {
      customer {
        hasTags(tags: [{ tag: "B2B" }]) {
          tag
          hasTag
        }
      }
    }
  }
  paymentMethods {
    id
    name
  }
}

Étape 3.3 : Logique (src/run.js)


const NO_CHANGES = { operations: [] };

export function run(input) {
  const tagCheck = input.cart?.buyerIdentity?.customer?.hasTags?.[0];
  const isB2B = tagCheck?.hasTag === true;
  if (!isB2B) return NO_CHANGES;

  const codMethod = input.paymentMethods.find((pm) =>
    pm.name.toLowerCase().includes("cash on delivery")
  );
  if (!codMethod) return NO_CHANGES;

  return {
    operations: [{ hide: { paymentMethodId: codMethod.id } }],
  };
}
const NO_CHANGES = { operations: [] };

export function run(input) {
  const tagCheck = input.cart?.buyerIdentity?.customer?.hasTags?.[0];
  const isB2B = tagCheck?.hasTag === true;
  if (!isB2B) return NO_CHANGES;

  const codMethod = input.paymentMethods.find((pm) =>
    pm.name.toLowerCase().includes("cash on delivery")
  );
  if (!codMethod) return NO_CHANGES;

  return {
    operations: [{ hide: { paymentMethodId: codMethod.id } }],
  };
}

Étape 3.4 : Activation

Les Payment Customizations disposent également d'une interface d'administration sous Settings → Payments → Customizations. Même processus que pour la livraison — sélectionnez votre Function, enregistrez, terminé.

Puisque vous lisez ceci — Un mot sur le post-achat

Une brève mise au point puisque vous êtes sur le blog de Revize. Revize gère ce que les Functions ne peuvent pas toucher — une fois la commande passée, les clients veulent ajouter un article, changer de taille, corriger l'adresse de livraison ou appliquer une remise oubliée. Les Functions interviennent lors du passage à la caisse. Revize intervient après. Les Functions déterminent ce qui est autorisé dans le panier ; Revize permet à vos clients et à votre équipe support de modifier la commande après coup sans passer par un cycle d'annulation et de réédition. Cela compte pour deux types de boutiques : celles avec un volume de commandes tel que la modification manuelle devient impossible (les boutiques Plus, évidemment, mais aussi les boutiques Advanced à fort trafic), et celles dont l'image de marque repose sur l'expérience client — où un e-mail indiquant « désolé, nous ne pouvons pas modifier cela » nuit à la fidélisation.

Si votre plan de migration prévoit de passer des Scripts aux Functions mais que vous n'avez pas encore résolu la modification des commandes post-achat, vous vous heurterez rapidement à un autre obstacle. Le guide de gestion des commandes que nous venons de publier présente l'ensemble des bonnes pratiques post-achat.

Revenons à la migration.

Stratégie de test : La méthode des clients taggués

Les Functions n'ont pas de « mode brouillon » activable dans l'admin. La méthode professionnelle consiste à conditionner la nouvelle Function à un tag client, à exécuter l'ancien Script et la nouvelle Function en parallèle, à vérifier qu'ils produisent un résultat identique pour les utilisateurs taggués, puis à basculer définitivement.

Étape 1 : Taguez vos utilisateurs de test

Dans Customers, ajoutez le tag FN-TESTER à deux ou trois comptes internes.

Étape 2 : Conditionner la Function à la présence du tag


// Au début de votre fonction run
let is_tester = input
    .cart()
    .buyer_identity()
    .and_then(|bi| bi.customer())
    .map(|c| c.has_any_tag())
    .unwrap_or(&false);

if !*is_tester {
    return Ok(default_result);  // Passage à l'ancien Script existant
}

// La logique de la nouvelle Function s'exécute uniquement pour les utilisateurs taggués
// Au début de votre fonction run
let is_tester = input
    .cart()
    .buyer_identity()
    .and_then(|bi| bi.customer())
    .map(|c| c.has_any_tag())
    .unwrap_or(&false);

if !*is_tester {
    return Ok(default_result);  // Passage à l'ancien Script existant
}

// La logique de la nouvelle Function s'exécute uniquement pour les utilisateurs taggués

Étape 3 : Ajoutez hasAnyTag à votre requête d'entrée


cart {
  buyerIdentity {
    customer {
      hasAnyTag(tags: ["FN-TESTER"])
    }
  }
}
cart {
  buyerIdentity {
    customer {
      hasAnyTag(tags: ["FN-TESTER"])
    }
  }
}

Étape 4 : Vérifier dans le processus d'achat

Connectez-vous avec un compte taggué, passez commande, confirmez que la Function s'active. Connectez-vous avec un compte non taggué, confirmez que l'ancien Script s'exécute toujours. Une fois la parité validée sur quelques jours, retirez la vérification du tag pour appliquer la Function à tous.

Étape 5 : Désactiver l'ancien Script

Allez dans Apps → Script Editor → [Votre Script] → Unpublish. Une fois désactivé, la Function devient la seule source de vérité.

Workflow de déploiement évolutif

Ne déployez pas indéfiniment depuis l'ordinateur d'un développeur. Une fois un ou deux Scripts migrés, configurez un véritable pipeline CI.

Le workflow minimal viable


# .github/workflows/deploy-functions.yml
name: Deploy Shopify Functions
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - uses: dtolnay/rust-toolchain@stable
        with: { targets: wasm32-wasip1 }
      - run: npm install -g @shopify/cli@latest
      - run: shopify app deploy --force
        env:
          SHOPIFY_CLI_PARTNERS_TOKEN: ${{ secrets.SHOPIFY_CLI_PARTNERS_TOKEN }}
# .github/workflows/deploy-functions.yml
name: Deploy Shopify Functions
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - uses: dtolnay/rust-toolchain@stable
        with: { targets: wasm32-wasip1 }
      - run: npm install -g @shopify/cli@latest
      - run: shopify app deploy --force
        env:
          SHOPIFY_CLI_PARTNERS_TOKEN: ${{ secrets.SHOPIFY_CLI_PARTNERS_TOKEN }}

Générez le jeton de partenaire depuis votre tableau de bord Partner sous Settings → Tokens. Désormais, chaque fusion sur main déploie vos Functions. Fini les discussions sur Slack pour savoir qui a déployé la dernière version.

Gestion des versions et retour arrière

shopify app deploy crée un instantané versionné. Pour revenir en arrière :


shopify app versions list
shopify app release --version <previous-version-id

shopify app versions list
shopify app release --version <previous-version-id

Par rapport aux Scripts — où le retour arrière nécessitait de retrouver l'ancien code pour le recoller — la différence est radicale.



Shopify Functions deployment pipeline across local staging and production environments

Ce que la plupart des équipes ratent

Après avoir accompagné des marchands Plus dans cette migration l'année passée, les cinq mêmes erreurs reviennent systématiquement.

1. Traiter les Functions comme une simple copie conforme des Scripts. Ce n'est pas le cas. Une seule Function peut remplacer trois Scripts grâce à une logique d'embranchement plus propre. Analysez vos Scripts de manière globale avant de réécrire.

2. Oublier les scopes de lecture. De nombreuses Functions requièrent read_customers, read_orders ou write_discounts. Ajoutez-les dans shopify.app.toml sous scopes et ré-autorisez l'application, sinon votre requête d'entrée renverra null.

3. Lancer les Functions sur des clients non taggués sans test de parité. Même si votre code semble correct, des cas limites (panier vide, cartes-cadeaux, avoirs de boutique, brouillons B2B) révéleront des failles. Un déploiement progressif avec tag vous prend deux jours de plus mais vous évite une panne critique.

4. Ignorer le Customizations Report. C'est le meilleur inventaire de ce qui s'exécute réellement sur votre boutique. Ne migrez pas de mémoire — basez-vous sur ce rapport.

5. Hardcoder les IDs de collection et les tags clients. Utilisez la configuration de Function via les metafields si vous avez besoin de valeurs ajustables par le marchand. La CLI peut générer des configurations basées sur les metafields — consultez la documentation de Shopify à ce sujet.

Plan d'action pour les 75 prochains jours

Un planning réaliste pour aborder sereinement l'échéance du 30 juin.


Semaine

Action

Semaine 1 (cette semaine)

Consulter le Customizations Report. Inventorier chaque Script. Décider entre Function, application publique ou suppression.

Semaines 2–3

Configurer l'environnement de développement local. Générer la première Function. Migrer le Script le plus simple (généralement une règle de masquage de paiement).

Semaines 4–6

Migrer les Scripts de remise. Ce sont ceux qui prennent le plus de temps car la Discounts API est la plus complète. Réaliser des tests approfondis par tag.

Semaines 7–8

Migrer les Scripts de livraison. Activer les Delivery Customizations via l'Admin.

Semaines 9–10

Configurer le pipeline CI. Automatiser tous les déploiements.

Semaine 11 (mi-juin)

Vérification finale de parité. Désactiver tous les Scripts. Faire tourner la boutique uniquement avec les Functions pendant deux semaines.

30 juin

Date butoir. Tout fonctionne car vous avez terminé en avance.

Si vous commencez cette semaine, vous conservez une marge de sécurité. Si vous commencez en juin, vous n'en aurez pas.



Week-by-week migration roadmap from Shopify Scripts to Functions

Foire Aux Questions

Ai-je besoin de Shopify Plus pour utiliser les Functions?

Les Functions personnalisées nécessitent Shopify Plus, mais les Functions issues d'applications publiques fonctionnent sur tous les forfaits. Si vous n'êtes pas sur Plus, deux choix s'offrent à vous : installer une application publique depuis le Shopify App Store qui déploie la Function pour vous, ou passer à Plus pour coder vos propres Functions personnalisées. La plupart des grands marchands utilisant des Scripts possédaient déjà Plus, ce qui ne change presque rien en pratique.

Puis-je écrire des Functions en TypeScript?

Oui — TypeScript est entièrement pris en charge et la CLI le configure pour vous. Lorsque vous lancez shopify app generate extension et choisissez « JavaScript », le projet généré inclut les déclarations de types de import("../generated/api"). Vous pouvez renommer les fichiers en .ts et ajouter un tsconfig.json si vous préférez. Le fichier compilé final (WASM) est strictement identique quel que soit le langage source.

Quelle est la rapidité des Functions par rapport aux Scripts?

Les Functions s'exécutent généralement en moins de 5 ms — soit nettement plus vite que les Scripts Ruby. Comme elles sont compilées en WebAssembly et s'exécutent dans un environnement restreint, Shopify impose une limite d'exécution de 5 ms. Si votre Function la dépasse, l'opération est abandonnée et la Function ne renvoie rien. En pratique, une Function bien conçue nécessite 1 à 2 ms. Les performances sont bien supérieures à celles des Scripts.

Une Function peut-elle appeler une API externe?

Non — les Functions ne peuvent pas effectuer de requêtes réseau. Il s'agit uniquement de calcul pur : données du panier en entrée → opérations en sortie. Si vous avez besoin de données externes (recherche CRM, vérification d'inventaire en temps réel), vous devez soit stocker ces données dans des metafields au préalable, soit utiliser une autre méthode (App Proxy, webhooks, Cart Transform avec appel back-end). C'est la raison la plus fréquente pour laquelle les équipes doivent repenser l'architecture plutôt que de faire un simple portage.

Quelle est la différence entre Cart Transform et les remises?

Les remises modifient les prix, tandis que Cart Transform modifie le contenu du panier. Utilisez la Discounts API pour appliquer un rabais de 10 %, offrir la livraison ou proposer une offre de type BOGO. Utilisez Cart Transform pour regrouper deux produits en un seul article, ou diviser une variante en plusieurs. De nombreux anciens Scripts mélangeaient ces deux aspects — lors de la migration, séparez-les en deux Functions distinctes.

Comment tester une Function localement sans boutique de développement?

Vous pouvez exécuter des tests unitaires avec cargo test (Rust) ou npm test (JS), mais les tests d'intégration complets requièrent une boutique de développement. La CLI propose shopify app function run qui exécute votre Function avec un fichier d'entrée de test — idéal pour itérer rapidement. Mais pour valider le comportement final du passage à la caisse de bout en bout, vous avez besoin d'une véritable boutique avec un panier réel.

Puis-je avoir plusieurs Functions du même type?

Oui — Shopify prend en charge plusieurs Functions par cible, et elles s'exécutent dans un ordre déterminé. Pour les remises, l'ordre est régi par les règles de cumul de Shopify. Pour les Delivery et Payment Customizations, vous pouvez chaîner les Functions, la sortie de l'une alimentant l'entrée de la suivante. La plupart des équipes utilisent une seule Function par type pour simplifier la gestion.

Qu'advient-il de mon Script après le déploiement de la Function?

Les deux s'exécutent en parallèle jusqu'à ce que vous désactiviez le Script dans Apps → Script Editor. Cela est intentionnel et vous permet de réaliser vos tests en conditions réelles. Après validation de la Function, désactivez manuellement le Script. Après le 30 juin 2026, tous les Scripts cesseront de s'exécuter, qu'ils soient désactivés ou non.

La migration aura-t-elle un impact sur mon SEO ou mon thème?

Non — les Functions s'exécutent côté serveur lors du passage à la caisse et n'interfèrent jamais avec votre thème ou vos pages produits. Elles modifient uniquement les remises, les options de livraison et les méthodes de paiement lors du paiement. Votre boutique en ligne, vos fiches produits et votre SEO restent inchangés.

Comment migrer un Script qui utilise Input.line_items avec des propriétés personnalisées?

Les propriétés personnalisées sont accessibles via le champ attribute des lignes du panier dans l'entrée GraphQL. Ajoutez attribute(key: "votre-cle") { value } dans la sélection lines. La Function les lit de la même manière que les Scripts lisaient les propriétés d'articles, mais via GraphQL plutôt que par des appels de méthodes Ruby.

Qu'en est-il des analyses de données et des tags de commande? Les Functions peuvent-elles écrire des données?

Les Functions ne peuvent pas écrire de tags de commande ni déclencher de webhooks — elles renvoient uniquement des opérations sur le panier en cours. Pour le taggage ou les flux de travail en aval, utilisez Shopify Flow déclenché par l'événement de création de commande. De nombreux marchands associent une Function (pour la remise) à un Flow (pour ajouter le tag « VOLUME-DISCOUNT-APPLIED » sur la commande).

Existe-t-il une application publique que je peux installer au lieu de développer une Function personnalisée?

Oui — le Shopify App Store propose des dizaines d'applications qui intègrent des Functions pour les cas d'usage courants. Recherchez « discount function », « delivery customization » ou « payment customization ». Pour des besoins classiques (remises sur volume, masquage de paiement par tag, livraison gratuite dès X $), une application existante peut vous éviter des jours de développement. Réservez les Functions personnalisées aux logiques réellement spécifiques à votre activité.

Que se passe-t-il si je dépasse la date limite du 30 juin?

Le Script s'arrête — il n'y a pas de solution de repli, pas de période de grâce et aucun report possible. Quelle que soit la fonction du Script (remise, masquage de tarif de livraison, blocage de paiement), le comportement par défaut sera rétabli à minuit UTC le 1er juillet. Si votre activité dépend de cette logique, prévoyez d'être opérationnel bien avant cette date. La migration prend généralement plus de temps que prévu, notamment en raison des tests de parité.

Puis-je supprimer définitivement l'application Script Editor?

Vous pourrez la désinstaller après le 30 juin 2026, mais Shopify la retirera probablement d'office. Une fois que les Scripts ne s'exécutent plus, l'éditeur n'a plus d'utilité. Vous pouvez également désactiver tous vos Scripts dès maintenant et désinstaller l'application immédiatement si votre migration est terminée — vos Functions fonctionnent de manière autonome.

Ce qu'il faut faire cette semaine

Ne vous contentez pas de lire cet article. Réalisez ces quatre actions dans les sept prochains jours.

1. Récupérer le Customizations Report. Allez dans Settings → Checkout → Customizations Report. Exportez-le. C'est votre base de travail pour la migration.

2. Configurer votre environnement de dev. Installez Node 18+, la Shopify CLI et Rust (si nécessaire). Vérifiez que shopify version fonctionne. Durée estimée : 30 minutes.

3. Générer et déployer une petite Function sur une boutique de dev. Choisissez le Script le plus simple — souvent une règle de masquage de paiement. Migrez-le de bout en bout. Même s'il ne va pas en production, vous aurez validé votre environnement de travail.

4. Bloquer des créneaux dans votre calendrier pour les huit prochaines semaines. Une migration ne se fait pas à la va-vite entre deux tâches quotidiennes. Réservez des plages régulières — par exemple chaque mardi et jeudi après-midi — et traitez ce projet comme une priorité absolue.

Parmi les équipes que nous avons accompagnées, le schéma reste le même : deux semaines d'attente, trois semaines de développement réel, une semaine de finalisation. Cela représente six semaines. Il vous en reste dix. Profitez de cette marge pour la revue de code et l'assurance qualité, sans repousser le lancement du projet.

Et une fois la logique de paiement opérationnelle, l'étape suivante pour la plupart des marchands est le post-achat — modifications d'adresses, échanges d'articles ou ajouts de remises après commande. Si cela fait partie de vos projets (et cela devrait être le cas, que vous soyez un marchand Plus à fort volume ou une boutique Advanced axée sur l'expérience client), Revize est disponible sur le Shopify App Store et fonctionne en parfaite synergie avec toutes les Functions que vous développerez.

Ressources


Articles connexes


Mis à jour en août 2026. Revize est une application Shopify permettant aux clients de modifier eux-mêmes leurs commandes après l'achat. Elle permet aux acheteurs de modifier leur adresse de livraison, d'échanger une variante ou un produit, d'annuler et d'obtenir un remboursement ou un avoir avant le traitement de la commande, le tout sans ouvrir de ticket d'assistance. En savoir plus sur la possibilité de permettre aux clients de modifier leurs propres commandes Shopify, ou retrouver Revize sur le Shopify App Store.

Nous sommes le 16 avril 2026. Hier, le 15 avril, Shopify a verrouillé définitivement le Script Editor. Vous ne pouvez plus créer ni publier de nouveau Script. Cette échéance est particulièrement critique pour la logique post-achat : les modifications d'adresse de livraison représentent la modification post-achat numéro 1, comptant pour 30.2 % de toutes les commandes modifiées (Revize, 2026), et tout Script gérant encore ces modifications est désormais figé. L'arrêt complet de l'exécution intervient dans 75 jours, le 30 juin 2026.

Si vous êtes un développeur Shopify Plus — ou l'agence gérant une boutique Plus — et que vous avez repoussé cette migration au « prochain sprint » ces douze derniers mois, vous avez un problème. Pas un problème secondaire. Un problème du type « votre passage à la caisse plante à minuit le 1er juillet ». La plupart des boutiques Plus ont accumulé entre 5 et 20 Scripts au fil des ans, chacun gérant discrètement une règle de remise, un masquage de livraison ou une passerelle de paiement que personne ne se rappelle avoir codé.

Ce guide est le manuel de migration technique que nous aurions aimé avoir en janvier. Il traite du code réel — pas seulement de la stratégie. À la fin de votre lecture, vous saurez comment structurer une Function avec la Shopify CLI, écrire la logique en Rust ou JavaScript pour les remises, les personnalisations de livraison et de paiement, la tester en toute sécurité sur un sous-ensemble ciblé de vos clients, et la déployer en production sans perturber votre processus d'achat actuel.

Retirons les Scripts de votre boutique et installons les Functions.



Developer migrating Shopify Scripts to Shopify Functions modules

Réponse rapide : Scripts → Functions en 60 secondes

La migration en un paragraphe : Les Shopify Scripts (code Ruby dans le Script Editor, réservés à Plus) sont remplacés par les Shopify Functions (modules WebAssembly écrits en Rust ou JavaScript, disponibles pour tous les forfaits). Vous générez une Function avec shopify app generate extension, écrivez une requête run.graphql qui récupère les données de panier nécessaires, écrivez un fichier run.rs ou run.js qui renvoie les opérations (remises, modes de livraison masqués, etc.), puis déployez avec shopify app deploy et l'activez via l'Admin ou une mutation GraphQL. Les Functions s'exécutent sous forme de WASM compilé avec une latence inférieure à 5 ms, fonctionnent sur tous les forfaits et constituent la seule méthode de personnalisation prise en charge par Shopify à l'avenir.

Ce qui change réellement le 30 juin

Avant de toucher au code, clarifions les dates. Il y en a deux, et les deux sont cruciales.


Date

Ce qui se passe

Votre action

15 avril 2026 (passé)

Script Editor en lecture seule. Aucun nouveau Script. Aucune modification des Scripts existants.

Les Scripts existants s'exécutent encore. Migrez maintenant ou figez votre logique.

30 juin 2026

Tous les Shopify Scripts cessent de s'exécuter. Définitivement.

Votre Function de remplacement doit être active avant cette date.

La migration est binaire. Soit votre Function est déployée d'ici le 30 juin et votre passage à la caisse continue de fonctionner, soit elle ne l'est pas — et chaque panier concerné revient silencieusement aux tarifs standards, aux modes de livraison par défaut et à l'activation de toutes les méthodes de paiement. Pas de demi-mesure. Le Script s'exécute ou ne s'exécute pas, et après le 30 juin, il ne s'exécute plus.

Conseil : Allez dans Settings → Checkout → Customizations Report dans votre admin Shopify. Vous y trouverez la liste de tous les Scripts actifs sur votre boutique, leur rôle et le type de Function de remplacement recommandé. Commencez par là.

Functions vs Scripts : Ce qui a changé


Dimension

Shopify Scripts (obsolète)

Shopify Functions (remplacement)

Langage

Ruby DSL (spécifique à Shopify)

Rust, JavaScript, TypeScript

Runtime

Ruby sandboxé sur l'infra Shopify

WebAssembly (WASM) — exécution < 5 ms

Disponibilité forfait

Plus uniquement

Tous les forfaits (les applications personnalisées nécessitent Plus ; les applications publiques sont ouvertes)

Éditeur

Script Editor dans l'admin

IDE local + Shopify CLI

Contrôle de version

Aucun — modifications en direct

Compatible Git — contrôle de version complet

Tests

Manuels dans le processus d'achat

Développement local avec shopify app dev, liens de prévisualisation

Déploiement

Clic sur « Enregistrer » dans l'admin

shopify app deploy depuis le terminal

Cibles

Articles, livraison, paiements

Remises, Cart Transform, Validation, Delivery Customization, Payment Customization, Order Routing, Fulfillment Constraints, et plus

Le changement d'architecture est majeur. Les Scripts consistaient à « modifier du Ruby dans une zone de texte ». Les Functions consistent à « écrire une véritable application, la soumettre au contrôle de version, la tester localement, la déployer via un vrai pipeline CI ». La courbe d'apprentissage est plus raide. C'est aussi la dernière migration de logique de paiement que vous ferez à moyen terme — les Functions représentent l'engagement à long terme de Shopify, pas une solution temporaire comme l'ont été les Scripts.

Associer vos Scripts au bon type de Function

Chaque Script actuel correspond à une API de Function spécifique. Voici le tableau de correspondance à garder sous les yeux.


Ancien type de Script

Rôle

Nouvelle API de Function

Cible de la Function

Line Item Script

Appliquer des remises à des produits / clients / conditions de panier spécifiques

Cart & Checkout Discounts API

cart.lines.discounts.generate.run

Shipping Script (remise)

Livraison gratuite / remisée selon les règles du panier

Cart & Checkout Discounts API

cart.delivery-options.discounts.generate.run

Shipping Script (masquer / renommer / réordonner)

Masquer un tarif de livraison au-dessus de X $, renommer « Standard » en « Gratuit dès 50 $ »

Delivery Customization API

cart.delivery-options.transform.run

Payment Script

Masquer PayPal pour le B2B, masquer le paiement à la livraison au-dessus de 500 $, réordonner les méthodes

Payment Customization API

cart.payment-methods.transform.run

Script modifiant le panier (rare)

Regrouper des produits, remplacer des articles

Cart Transform API

cart.transform.run

Script de blocage de commande

Rejeter le panier si le mélange de SKU est invalide

Cart & Checkout Validation API

cart.validations.generate.run

Si vous avez dix Scripts, vous développerez probablement trois à cinq Functions — plusieurs Scripts se regroupent souvent en une seule Function dotée d'une logique d'embranchement plus propre.



Shopify Functions unifying discounts, delivery, and payment customizations

Prérequis : Configurer votre environnement de développement local

Avant de générer une Function, vous devez installer trois outils localement. Exécutez ces vérifications dans votre terminal.

1. Node.js 18+


node --version
# Doit être >= 18.0.0

Si la version est plus ancienne, installez-la via nvm ou téléchargez-la depuis nodejs.org.

2. Shopify CLI 3+


npm install -g @shopify/cli@latest
shopify version
# Doit afficher 3.x ou plus

3. Toolchain Rust (uniquement si vous écrivez des Functions en Rust)


curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-wasip1
cargo --version

Les Functions en JavaScript n'ont pas besoin de Rust. Choisissez un langage pour votre équipe et tenez-vous-y — mélanger les deux augmente la charge de maintenance.

4. Une boutique de développement

Connectez-vous à votre tableau de bord Partner et créez une nouvelle boutique de développement, ou utilisez-en une existante. Vous y déploirez les Functions avant de les passer en production.

Générer votre première Function

La CLI génère la majeure partie du code de base. Dans n'importe quel répertoire :


# Créer une nouvelle application Shopify (ignorer si vous en avez déjà une)
shopify app init my-checkout-functions
cd my-checkout-functions

# Générer une extension de type Function
shopify app generate extension

La CLI vous guide à travers les étapes. Pour une Function de remise, vous choisirez :

  • Type: Function

  • Template: discount (ou cart_checkout_validation, delivery_customization, payment_customization, etc.)

  • Language: Rust ou JavaScript

  • Name: quelque chose comme volume-discount-fn

Cela crée le répertoire extensions/volume-discount-fn/ contenant :


extensions/volume-discount-fn/
├── shopify.extension.toml      # Config de la Function cibles, build, version
├── src/
├── cart_lines_discounts_generate_run.graphql   # Requête d'entrée
└── cart_lines_discounts_generate_run.rs        # Logique de la Function
├── Cargo.toml                  # Dépendances Rust (Rust uniquement)
└── README.md

Les trois fichiers que vous modifierez constamment sont le .toml (config), le .graphql (entrée) et le .rs / .js (logique). C'est tout.

Tutoriel 1 : Remplacer un Line Item Script (Remise sur volume)

Supposons que votre ancien Script offrait 10 % de réduction sur le sous-total de la commande dès que le panier contenait au moins 5 articles d'une collection spécifique. Voici l'équivalent avec une Function.

Étape 1.1 : La configuration (shopify.extension.toml)


api_version = "2026-01"

[[extensions]]
name = "volume-discount-fn"
handle = "volume-discount-fn"
type = "function"

[[extensions.targeting]]
target = "cart.lines.discounts.generate.run"
input_query = "src/cart_lines_discounts_generate_run.graphql"
export = "cart_lines_discounts_generate_run"

[extensions.build]
command = "cargo build --target=wasm32-wasip1 --release"
path = "target/wasm32-wasip1/release/volume-discount-fn.wasm"
watch = ["src/**/*.rs"]

Étape 1.2 : La requête d'entrée (src/cart_lines_discounts_generate_run.graphql)


query Input {
  cart {
    lines {
      id
      quantity
      cost {
        subtotalAmount {
          amount
        }
      }
      merchandise {
        ... on ProductVariant {
          product {
            inAnyCollection(ids: ["gid://shopify/Collection/123456789"])
          }
        }
      }
    }
  }
  discount {
    discountClasses
  }
}

Conseil : Les Functions ne voient que les données que vous demandez. Gardez le GraphQL minimal — chaque champ omis permet une exécution plus rapide et moins coûteuse.

Étape 1.3 : La logique (src/cart_lines_discounts_generate_run.rs)


use super::schema;
use shopify_function::prelude::*;
use shopify_function::Result;

#[shopify_function]
fn cart_lines_discounts_generate_run(
    input: schema::cart_lines_discounts_generate_run::Input,
) -> Result<schema::CartLinesDiscountsGenerateRunResult> {
    // Sortie si la classe de remise ne correspond pas
    let has_order_discount = input
        .discount()
        .discount_classes()
        .contains(&schema::DiscountClass::Order);

    if !has_order_discount {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Somme des quantités d'articles de la collection cible
    let qualifying_qty: i64 = input
        .cart()
        .lines()
        .iter()
        .filter(|line| {
            if let schema::Merchandise::ProductVariant(v) = line.merchandise() {
                *v.product().in_any_collection()
            } else {
                false
            }
        })
        .map(|line| *line.quantity())
        .sum();

    if qualifying_qty < 5 {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Appliquer 10 % de réduction sur le sous-total de la commande
    Ok(schema::CartLinesDiscountsGenerateRunResult {
        operations: vec![schema::CartOperation::OrderDiscountsAdd(
            schema::OrderDiscountsAddOperation {
                selection_strategy: schema::OrderDiscountSelectionStrategy::First,
                candidates: vec![schema::OrderDiscountCandidate {
                    targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal(
                        schema::OrderSubtotalTarget {
                            excluded_cart_line_ids: vec![],
                        },
                    )],
                    message: Some("Volume discount: 10% off".to_string()),
                    value: schema::OrderDiscountCandidateValue::Percentage(
                        schema::Percentage { value: Decimal(10.0) }
                    ),
                    conditions: None,
                    associated_discount_code: None,
                }],
            },
        )],
    })
}

Étape 1.4 : Tester, déployer, activer


# Développement local avec rechargement à chaud
shopify app dev

# Une fois prêt, déployez
shopify app deploy

# Dans le panneau GraphiQL qui s'ouvre (appuyez sur `g` dans le terminal de dev),
# créez la remise automatique qui utilise votre Function :
mutation {
  discountAutomaticAppCreate(
    automaticAppDiscount: {
      title: "Volume Discount (5+ collection items)"
      functionHandle: "volume-discount-fn"
      discountClasses: [ORDER]
      startsAt: "2026-04-16T00:00:00Z"
    }
  ) {
    automaticAppDiscount { discountId }
    userErrors { field message }
  }
}

C'est tout. La Function est active, soumise au contrôle de version et remplace complètement l'ancien Script.

Tutoriel 2 : Remplacer un Shipping Script (Masquer une méthode au-dessus d'un seuil de panier)

Un Script classique : « Masquer la livraison Express lorsque le sous-total du panier dépasse 500 $ pour éviter des envois urgents coûteux sur de grosses commandes ». Voici la version Function de type Delivery Customization.

Étape 2.1 : Génération du code


shopify app generate extension --template delivery_customization --name hide-express-fn

Étape 2.2 : Requête d'entrée (src/run.graphql)


query Input {
  cart {
    cost {
      subtotalAmount {
        amount
      }
    }
    deliveryGroups {
      deliveryOptions {
        handle
        title
      }
    }
  }
}

Étape 2.3 : Logique (src/run.js — variante JavaScript)


// @ts-check
/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

const NO_CHANGES = { operations: [] };
const THRESHOLD = 500.0;
const HIDE_TITLES = ["Express", "Overnight"];

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const subtotal = parseFloat(input.cart.cost.subtotalAmount.amount);
  if (subtotal < THRESHOLD) return NO_CHANGES;

  const operations = input.cart.deliveryGroups.flatMap((group) =>
    group.deliveryOptions
      .filter((opt) => HIDE_TITLES.some((t) => opt.title.includes(t)))
      .map((opt) => ({
        hide: { deliveryOptionHandle: opt.handle },
      }))
  );

  return { operations };
}

Étape 2.4 : Activation via l'Admin (aucune mutation GraphQL requise)

Les Delivery Customizations disposent d'une interface d'administration intégrée. Après shopify app deploy :

  1. Allez dans Settings → Shipping and delivery

  2. Faites défiler jusqu'à la section Customizations en bas

  3. Cliquez sur Add customization → sélectionnez votre Function

  4. Enregistrez

La règle de masquage est active en production. Aucune mutation requise.



Shopify delivery customization Function hiding shipping option at checkout

Tutoriel 3 : Remplacer un Payment Script (Masquer le paiement à la livraison pour le B2B)

Ancien Script : « Masquer le paiement à la livraison pour tout client ayant le tag 'B2B' ». Voici la version Payment Customization.

Étape 3.1 : Génération du code


shopify app generate extension --template payment_customization --name hide-cod-b2b-fn

Étape 3.2 : Requête d'entrée


query Input {
  cart {
    buyerIdentity {
      customer {
        hasTags(tags: [{ tag: "B2B" }]) {
          tag
          hasTag
        }
      }
    }
  }
  paymentMethods {
    id
    name
  }
}

Étape 3.3 : Logique (src/run.js)


const NO_CHANGES = { operations: [] };

export function run(input) {
  const tagCheck = input.cart?.buyerIdentity?.customer?.hasTags?.[0];
  const isB2B = tagCheck?.hasTag === true;
  if (!isB2B) return NO_CHANGES;

  const codMethod = input.paymentMethods.find((pm) =>
    pm.name.toLowerCase().includes("cash on delivery")
  );
  if (!codMethod) return NO_CHANGES;

  return {
    operations: [{ hide: { paymentMethodId: codMethod.id } }],
  };
}

Étape 3.4 : Activation

Les Payment Customizations disposent également d'une interface d'administration sous Settings → Payments → Customizations. Même processus que pour la livraison — sélectionnez votre Function, enregistrez, terminé.

Puisque vous lisez ceci — Un mot sur le post-achat

Une brève mise au point puisque vous êtes sur le blog de Revize. Revize gère ce que les Functions ne peuvent pas toucher — une fois la commande passée, les clients veulent ajouter un article, changer de taille, corriger l'adresse de livraison ou appliquer une remise oubliée. Les Functions interviennent lors du passage à la caisse. Revize intervient après. Les Functions déterminent ce qui est autorisé dans le panier ; Revize permet à vos clients et à votre équipe support de modifier la commande après coup sans passer par un cycle d'annulation et de réédition. Cela compte pour deux types de boutiques : celles avec un volume de commandes tel que la modification manuelle devient impossible (les boutiques Plus, évidemment, mais aussi les boutiques Advanced à fort trafic), et celles dont l'image de marque repose sur l'expérience client — où un e-mail indiquant « désolé, nous ne pouvons pas modifier cela » nuit à la fidélisation.

Si votre plan de migration prévoit de passer des Scripts aux Functions mais que vous n'avez pas encore résolu la modification des commandes post-achat, vous vous heurterez rapidement à un autre obstacle. Le guide de gestion des commandes que nous venons de publier présente l'ensemble des bonnes pratiques post-achat.

Revenons à la migration.

Stratégie de test : La méthode des clients taggués

Les Functions n'ont pas de « mode brouillon » activable dans l'admin. La méthode professionnelle consiste à conditionner la nouvelle Function à un tag client, à exécuter l'ancien Script et la nouvelle Function en parallèle, à vérifier qu'ils produisent un résultat identique pour les utilisateurs taggués, puis à basculer définitivement.

Étape 1 : Taguez vos utilisateurs de test

Dans Customers, ajoutez le tag FN-TESTER à deux ou trois comptes internes.

Étape 2 : Conditionner la Function à la présence du tag


// Au début de votre fonction run
let is_tester = input
    .cart()
    .buyer_identity()
    .and_then(|bi| bi.customer())
    .map(|c| c.has_any_tag())
    .unwrap_or(&false);

if !*is_tester {
    return Ok(default_result);  // Passage à l'ancien Script existant
}

// La logique de la nouvelle Function s'exécute uniquement pour les utilisateurs taggués

Étape 3 : Ajoutez hasAnyTag à votre requête d'entrée


cart {
  buyerIdentity {
    customer {
      hasAnyTag(tags: ["FN-TESTER"])
    }
  }
}

Étape 4 : Vérifier dans le processus d'achat

Connectez-vous avec un compte taggué, passez commande, confirmez que la Function s'active. Connectez-vous avec un compte non taggué, confirmez que l'ancien Script s'exécute toujours. Une fois la parité validée sur quelques jours, retirez la vérification du tag pour appliquer la Function à tous.

Étape 5 : Désactiver l'ancien Script

Allez dans Apps → Script Editor → [Votre Script] → Unpublish. Une fois désactivé, la Function devient la seule source de vérité.

Workflow de déploiement évolutif

Ne déployez pas indéfiniment depuis l'ordinateur d'un développeur. Une fois un ou deux Scripts migrés, configurez un véritable pipeline CI.

Le workflow minimal viable


# .github/workflows/deploy-functions.yml
name: Deploy Shopify Functions
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - uses: dtolnay/rust-toolchain@stable
        with: { targets: wasm32-wasip1 }
      - run: npm install -g @shopify/cli@latest
      - run: shopify app deploy --force
        env:
          SHOPIFY_CLI_PARTNERS_TOKEN: ${{ secrets.SHOPIFY_CLI_PARTNERS_TOKEN }}

Générez le jeton de partenaire depuis votre tableau de bord Partner sous Settings → Tokens. Désormais, chaque fusion sur main déploie vos Functions. Fini les discussions sur Slack pour savoir qui a déployé la dernière version.

Gestion des versions et retour arrière

shopify app deploy crée un instantané versionné. Pour revenir en arrière :


shopify app versions list
shopify app release --version <previous-version-id

Par rapport aux Scripts — où le retour arrière nécessitait de retrouver l'ancien code pour le recoller — la différence est radicale.



Shopify Functions deployment pipeline across local staging and production environments

Ce que la plupart des équipes ratent

Après avoir accompagné des marchands Plus dans cette migration l'année passée, les cinq mêmes erreurs reviennent systématiquement.

1. Traiter les Functions comme une simple copie conforme des Scripts. Ce n'est pas le cas. Une seule Function peut remplacer trois Scripts grâce à une logique d'embranchement plus propre. Analysez vos Scripts de manière globale avant de réécrire.

2. Oublier les scopes de lecture. De nombreuses Functions requièrent read_customers, read_orders ou write_discounts. Ajoutez-les dans shopify.app.toml sous scopes et ré-autorisez l'application, sinon votre requête d'entrée renverra null.

3. Lancer les Functions sur des clients non taggués sans test de parité. Même si votre code semble correct, des cas limites (panier vide, cartes-cadeaux, avoirs de boutique, brouillons B2B) révéleront des failles. Un déploiement progressif avec tag vous prend deux jours de plus mais vous évite une panne critique.

4. Ignorer le Customizations Report. C'est le meilleur inventaire de ce qui s'exécute réellement sur votre boutique. Ne migrez pas de mémoire — basez-vous sur ce rapport.

5. Hardcoder les IDs de collection et les tags clients. Utilisez la configuration de Function via les metafields si vous avez besoin de valeurs ajustables par le marchand. La CLI peut générer des configurations basées sur les metafields — consultez la documentation de Shopify à ce sujet.

Plan d'action pour les 75 prochains jours

Un planning réaliste pour aborder sereinement l'échéance du 30 juin.


Semaine

Action

Semaine 1 (cette semaine)

Consulter le Customizations Report. Inventorier chaque Script. Décider entre Function, application publique ou suppression.

Semaines 2–3

Configurer l'environnement de développement local. Générer la première Function. Migrer le Script le plus simple (généralement une règle de masquage de paiement).

Semaines 4–6

Migrer les Scripts de remise. Ce sont ceux qui prennent le plus de temps car la Discounts API est la plus complète. Réaliser des tests approfondis par tag.

Semaines 7–8

Migrer les Scripts de livraison. Activer les Delivery Customizations via l'Admin.

Semaines 9–10

Configurer le pipeline CI. Automatiser tous les déploiements.

Semaine 11 (mi-juin)

Vérification finale de parité. Désactiver tous les Scripts. Faire tourner la boutique uniquement avec les Functions pendant deux semaines.

30 juin

Date butoir. Tout fonctionne car vous avez terminé en avance.

Si vous commencez cette semaine, vous conservez une marge de sécurité. Si vous commencez en juin, vous n'en aurez pas.



Week-by-week migration roadmap from Shopify Scripts to Functions

Foire Aux Questions

Ai-je besoin de Shopify Plus pour utiliser les Functions?

Les Functions personnalisées nécessitent Shopify Plus, mais les Functions issues d'applications publiques fonctionnent sur tous les forfaits. Si vous n'êtes pas sur Plus, deux choix s'offrent à vous : installer une application publique depuis le Shopify App Store qui déploie la Function pour vous, ou passer à Plus pour coder vos propres Functions personnalisées. La plupart des grands marchands utilisant des Scripts possédaient déjà Plus, ce qui ne change presque rien en pratique.

Puis-je écrire des Functions en TypeScript?

Oui — TypeScript est entièrement pris en charge et la CLI le configure pour vous. Lorsque vous lancez shopify app generate extension et choisissez « JavaScript », le projet généré inclut les déclarations de types de import("../generated/api"). Vous pouvez renommer les fichiers en .ts et ajouter un tsconfig.json si vous préférez. Le fichier compilé final (WASM) est strictement identique quel que soit le langage source.

Quelle est la rapidité des Functions par rapport aux Scripts?

Les Functions s'exécutent généralement en moins de 5 ms — soit nettement plus vite que les Scripts Ruby. Comme elles sont compilées en WebAssembly et s'exécutent dans un environnement restreint, Shopify impose une limite d'exécution de 5 ms. Si votre Function la dépasse, l'opération est abandonnée et la Function ne renvoie rien. En pratique, une Function bien conçue nécessite 1 à 2 ms. Les performances sont bien supérieures à celles des Scripts.

Une Function peut-elle appeler une API externe?

Non — les Functions ne peuvent pas effectuer de requêtes réseau. Il s'agit uniquement de calcul pur : données du panier en entrée → opérations en sortie. Si vous avez besoin de données externes (recherche CRM, vérification d'inventaire en temps réel), vous devez soit stocker ces données dans des metafields au préalable, soit utiliser une autre méthode (App Proxy, webhooks, Cart Transform avec appel back-end). C'est la raison la plus fréquente pour laquelle les équipes doivent repenser l'architecture plutôt que de faire un simple portage.

Quelle est la différence entre Cart Transform et les remises?

Les remises modifient les prix, tandis que Cart Transform modifie le contenu du panier. Utilisez la Discounts API pour appliquer un rabais de 10 %, offrir la livraison ou proposer une offre de type BOGO. Utilisez Cart Transform pour regrouper deux produits en un seul article, ou diviser une variante en plusieurs. De nombreux anciens Scripts mélangeaient ces deux aspects — lors de la migration, séparez-les en deux Functions distinctes.

Comment tester une Function localement sans boutique de développement?

Vous pouvez exécuter des tests unitaires avec cargo test (Rust) ou npm test (JS), mais les tests d'intégration complets requièrent une boutique de développement. La CLI propose shopify app function run qui exécute votre Function avec un fichier d'entrée de test — idéal pour itérer rapidement. Mais pour valider le comportement final du passage à la caisse de bout en bout, vous avez besoin d'une véritable boutique avec un panier réel.

Puis-je avoir plusieurs Functions du même type?

Oui — Shopify prend en charge plusieurs Functions par cible, et elles s'exécutent dans un ordre déterminé. Pour les remises, l'ordre est régi par les règles de cumul de Shopify. Pour les Delivery et Payment Customizations, vous pouvez chaîner les Functions, la sortie de l'une alimentant l'entrée de la suivante. La plupart des équipes utilisent une seule Function par type pour simplifier la gestion.

Qu'advient-il de mon Script après le déploiement de la Function?

Les deux s'exécutent en parallèle jusqu'à ce que vous désactiviez le Script dans Apps → Script Editor. Cela est intentionnel et vous permet de réaliser vos tests en conditions réelles. Après validation de la Function, désactivez manuellement le Script. Après le 30 juin 2026, tous les Scripts cesseront de s'exécuter, qu'ils soient désactivés ou non.

La migration aura-t-elle un impact sur mon SEO ou mon thème?

Non — les Functions s'exécutent côté serveur lors du passage à la caisse et n'interfèrent jamais avec votre thème ou vos pages produits. Elles modifient uniquement les remises, les options de livraison et les méthodes de paiement lors du paiement. Votre boutique en ligne, vos fiches produits et votre SEO restent inchangés.

Comment migrer un Script qui utilise Input.line_items avec des propriétés personnalisées?

Les propriétés personnalisées sont accessibles via le champ attribute des lignes du panier dans l'entrée GraphQL. Ajoutez attribute(key: "votre-cle") { value } dans la sélection lines. La Function les lit de la même manière que les Scripts lisaient les propriétés d'articles, mais via GraphQL plutôt que par des appels de méthodes Ruby.

Qu'en est-il des analyses de données et des tags de commande? Les Functions peuvent-elles écrire des données?

Les Functions ne peuvent pas écrire de tags de commande ni déclencher de webhooks — elles renvoient uniquement des opérations sur le panier en cours. Pour le taggage ou les flux de travail en aval, utilisez Shopify Flow déclenché par l'événement de création de commande. De nombreux marchands associent une Function (pour la remise) à un Flow (pour ajouter le tag « VOLUME-DISCOUNT-APPLIED » sur la commande).

Existe-t-il une application publique que je peux installer au lieu de développer une Function personnalisée?

Oui — le Shopify App Store propose des dizaines d'applications qui intègrent des Functions pour les cas d'usage courants. Recherchez « discount function », « delivery customization » ou « payment customization ». Pour des besoins classiques (remises sur volume, masquage de paiement par tag, livraison gratuite dès X $), une application existante peut vous éviter des jours de développement. Réservez les Functions personnalisées aux logiques réellement spécifiques à votre activité.

Que se passe-t-il si je dépasse la date limite du 30 juin?

Le Script s'arrête — il n'y a pas de solution de repli, pas de période de grâce et aucun report possible. Quelle que soit la fonction du Script (remise, masquage de tarif de livraison, blocage de paiement), le comportement par défaut sera rétabli à minuit UTC le 1er juillet. Si votre activité dépend de cette logique, prévoyez d'être opérationnel bien avant cette date. La migration prend généralement plus de temps que prévu, notamment en raison des tests de parité.

Puis-je supprimer définitivement l'application Script Editor?

Vous pourrez la désinstaller après le 30 juin 2026, mais Shopify la retirera probablement d'office. Une fois que les Scripts ne s'exécutent plus, l'éditeur n'a plus d'utilité. Vous pouvez également désactiver tous vos Scripts dès maintenant et désinstaller l'application immédiatement si votre migration est terminée — vos Functions fonctionnent de manière autonome.

Ce qu'il faut faire cette semaine

Ne vous contentez pas de lire cet article. Réalisez ces quatre actions dans les sept prochains jours.

1. Récupérer le Customizations Report. Allez dans Settings → Checkout → Customizations Report. Exportez-le. C'est votre base de travail pour la migration.

2. Configurer votre environnement de dev. Installez Node 18+, la Shopify CLI et Rust (si nécessaire). Vérifiez que shopify version fonctionne. Durée estimée : 30 minutes.

3. Générer et déployer une petite Function sur une boutique de dev. Choisissez le Script le plus simple — souvent une règle de masquage de paiement. Migrez-le de bout en bout. Même s'il ne va pas en production, vous aurez validé votre environnement de travail.

4. Bloquer des créneaux dans votre calendrier pour les huit prochaines semaines. Une migration ne se fait pas à la va-vite entre deux tâches quotidiennes. Réservez des plages régulières — par exemple chaque mardi et jeudi après-midi — et traitez ce projet comme une priorité absolue.

Parmi les équipes que nous avons accompagnées, le schéma reste le même : deux semaines d'attente, trois semaines de développement réel, une semaine de finalisation. Cela représente six semaines. Il vous en reste dix. Profitez de cette marge pour la revue de code et l'assurance qualité, sans repousser le lancement du projet.

Et une fois la logique de paiement opérationnelle, l'étape suivante pour la plupart des marchands est le post-achat — modifications d'adresses, échanges d'articles ou ajouts de remises après commande. Si cela fait partie de vos projets (et cela devrait être le cas, que vous soyez un marchand Plus à fort volume ou une boutique Advanced axée sur l'expérience client), Revize est disponible sur le Shopify App Store et fonctionne en parfaite synergie avec toutes les Functions que vous développerez.

Ressources


Articles connexes


Mis à jour en août 2026. Revize est une application Shopify permettant aux clients de modifier eux-mêmes leurs commandes après l'achat. Elle permet aux acheteurs de modifier leur adresse de livraison, d'échanger une variante ou un produit, d'annuler et d'obtenir un remboursement ou un avoir avant le traitement de la commande, le tout sans ouvrir de ticket d'assistance. En savoir plus sur la possibilité de permettre aux clients de modifier leurs propres commandes Shopify, ou retrouver Revize sur le Shopify App Store.

Nous sommes le 16 avril 2026. Hier, le 15 avril, Shopify a verrouillé définitivement le Script Editor. Vous ne pouvez plus créer ni publier de nouveau Script. Cette échéance est particulièrement critique pour la logique post-achat : les modifications d'adresse de livraison représentent la modification post-achat numéro 1, comptant pour 30.2 % de toutes les commandes modifiées (Revize, 2026), et tout Script gérant encore ces modifications est désormais figé. L'arrêt complet de l'exécution intervient dans 75 jours, le 30 juin 2026.

Si vous êtes un développeur Shopify Plus — ou l'agence gérant une boutique Plus — et que vous avez repoussé cette migration au « prochain sprint » ces douze derniers mois, vous avez un problème. Pas un problème secondaire. Un problème du type « votre passage à la caisse plante à minuit le 1er juillet ». La plupart des boutiques Plus ont accumulé entre 5 et 20 Scripts au fil des ans, chacun gérant discrètement une règle de remise, un masquage de livraison ou une passerelle de paiement que personne ne se rappelle avoir codé.

Ce guide est le manuel de migration technique que nous aurions aimé avoir en janvier. Il traite du code réel — pas seulement de la stratégie. À la fin de votre lecture, vous saurez comment structurer une Function avec la Shopify CLI, écrire la logique en Rust ou JavaScript pour les remises, les personnalisations de livraison et de paiement, la tester en toute sécurité sur un sous-ensemble ciblé de vos clients, et la déployer en production sans perturber votre processus d'achat actuel.

Retirons les Scripts de votre boutique et installons les Functions.



Developer migrating Shopify Scripts to Shopify Functions modules

Réponse rapide : Scripts → Functions en 60 secondes

La migration en un paragraphe : Les Shopify Scripts (code Ruby dans le Script Editor, réservés à Plus) sont remplacés par les Shopify Functions (modules WebAssembly écrits en Rust ou JavaScript, disponibles pour tous les forfaits). Vous générez une Function avec shopify app generate extension, écrivez une requête run.graphql qui récupère les données de panier nécessaires, écrivez un fichier run.rs ou run.js qui renvoie les opérations (remises, modes de livraison masqués, etc.), puis déployez avec shopify app deploy et l'activez via l'Admin ou une mutation GraphQL. Les Functions s'exécutent sous forme de WASM compilé avec une latence inférieure à 5 ms, fonctionnent sur tous les forfaits et constituent la seule méthode de personnalisation prise en charge par Shopify à l'avenir.

Ce qui change réellement le 30 juin

Avant de toucher au code, clarifions les dates. Il y en a deux, et les deux sont cruciales.


Date

Ce qui se passe

Votre action

15 avril 2026 (passé)

Script Editor en lecture seule. Aucun nouveau Script. Aucune modification des Scripts existants.

Les Scripts existants s'exécutent encore. Migrez maintenant ou figez votre logique.

30 juin 2026

Tous les Shopify Scripts cessent de s'exécuter. Définitivement.

Votre Function de remplacement doit être active avant cette date.

La migration est binaire. Soit votre Function est déployée d'ici le 30 juin et votre passage à la caisse continue de fonctionner, soit elle ne l'est pas — et chaque panier concerné revient silencieusement aux tarifs standards, aux modes de livraison par défaut et à l'activation de toutes les méthodes de paiement. Pas de demi-mesure. Le Script s'exécute ou ne s'exécute pas, et après le 30 juin, il ne s'exécute plus.

Conseil : Allez dans Settings → Checkout → Customizations Report dans votre admin Shopify. Vous y trouverez la liste de tous les Scripts actifs sur votre boutique, leur rôle et le type de Function de remplacement recommandé. Commencez par là.

Functions vs Scripts : Ce qui a changé


Dimension

Shopify Scripts (obsolète)

Shopify Functions (remplacement)

Langage

Ruby DSL (spécifique à Shopify)

Rust, JavaScript, TypeScript

Runtime

Ruby sandboxé sur l'infra Shopify

WebAssembly (WASM) — exécution < 5 ms

Disponibilité forfait

Plus uniquement

Tous les forfaits (les applications personnalisées nécessitent Plus ; les applications publiques sont ouvertes)

Éditeur

Script Editor dans l'admin

IDE local + Shopify CLI

Contrôle de version

Aucun — modifications en direct

Compatible Git — contrôle de version complet

Tests

Manuels dans le processus d'achat

Développement local avec shopify app dev, liens de prévisualisation

Déploiement

Clic sur « Enregistrer » dans l'admin

shopify app deploy depuis le terminal

Cibles

Articles, livraison, paiements

Remises, Cart Transform, Validation, Delivery Customization, Payment Customization, Order Routing, Fulfillment Constraints, et plus

Le changement d'architecture est majeur. Les Scripts consistaient à « modifier du Ruby dans une zone de texte ». Les Functions consistent à « écrire une véritable application, la soumettre au contrôle de version, la tester localement, la déployer via un vrai pipeline CI ». La courbe d'apprentissage est plus raide. C'est aussi la dernière migration de logique de paiement que vous ferez à moyen terme — les Functions représentent l'engagement à long terme de Shopify, pas une solution temporaire comme l'ont été les Scripts.

Associer vos Scripts au bon type de Function

Chaque Script actuel correspond à une API de Function spécifique. Voici le tableau de correspondance à garder sous les yeux.


Ancien type de Script

Rôle

Nouvelle API de Function

Cible de la Function

Line Item Script

Appliquer des remises à des produits / clients / conditions de panier spécifiques

Cart & Checkout Discounts API

cart.lines.discounts.generate.run

Shipping Script (remise)

Livraison gratuite / remisée selon les règles du panier

Cart & Checkout Discounts API

cart.delivery-options.discounts.generate.run

Shipping Script (masquer / renommer / réordonner)

Masquer un tarif de livraison au-dessus de X $, renommer « Standard » en « Gratuit dès 50 $ »

Delivery Customization API

cart.delivery-options.transform.run

Payment Script

Masquer PayPal pour le B2B, masquer le paiement à la livraison au-dessus de 500 $, réordonner les méthodes

Payment Customization API

cart.payment-methods.transform.run

Script modifiant le panier (rare)

Regrouper des produits, remplacer des articles

Cart Transform API

cart.transform.run

Script de blocage de commande

Rejeter le panier si le mélange de SKU est invalide

Cart & Checkout Validation API

cart.validations.generate.run

Si vous avez dix Scripts, vous développerez probablement trois à cinq Functions — plusieurs Scripts se regroupent souvent en une seule Function dotée d'une logique d'embranchement plus propre.



Shopify Functions unifying discounts, delivery, and payment customizations

Prérequis : Configurer votre environnement de développement local

Avant de générer une Function, vous devez installer trois outils localement. Exécutez ces vérifications dans votre terminal.

1. Node.js 18+


node --version
# Doit être >= 18.0.0

Si la version est plus ancienne, installez-la via nvm ou téléchargez-la depuis nodejs.org.

2. Shopify CLI 3+


npm install -g @shopify/cli@latest
shopify version
# Doit afficher 3.x ou plus

3. Toolchain Rust (uniquement si vous écrivez des Functions en Rust)


curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-wasip1
cargo --version

Les Functions en JavaScript n'ont pas besoin de Rust. Choisissez un langage pour votre équipe et tenez-vous-y — mélanger les deux augmente la charge de maintenance.

4. Une boutique de développement

Connectez-vous à votre tableau de bord Partner et créez une nouvelle boutique de développement, ou utilisez-en une existante. Vous y déploirez les Functions avant de les passer en production.

Générer votre première Function

La CLI génère la majeure partie du code de base. Dans n'importe quel répertoire :


# Créer une nouvelle application Shopify (ignorer si vous en avez déjà une)
shopify app init my-checkout-functions
cd my-checkout-functions

# Générer une extension de type Function
shopify app generate extension

La CLI vous guide à travers les étapes. Pour une Function de remise, vous choisirez :

  • Type: Function

  • Template: discount (ou cart_checkout_validation, delivery_customization, payment_customization, etc.)

  • Language: Rust ou JavaScript

  • Name: quelque chose comme volume-discount-fn

Cela crée le répertoire extensions/volume-discount-fn/ contenant :


extensions/volume-discount-fn/
├── shopify.extension.toml      # Config de la Function cibles, build, version
├── src/
├── cart_lines_discounts_generate_run.graphql   # Requête d'entrée
└── cart_lines_discounts_generate_run.rs        # Logique de la Function
├── Cargo.toml                  # Dépendances Rust (Rust uniquement)
└── README.md

Les trois fichiers que vous modifierez constamment sont le .toml (config), le .graphql (entrée) et le .rs / .js (logique). C'est tout.

Tutoriel 1 : Remplacer un Line Item Script (Remise sur volume)

Supposons que votre ancien Script offrait 10 % de réduction sur le sous-total de la commande dès que le panier contenait au moins 5 articles d'une collection spécifique. Voici l'équivalent avec une Function.

Étape 1.1 : La configuration (shopify.extension.toml)


api_version = "2026-01"

[[extensions]]
name = "volume-discount-fn"
handle = "volume-discount-fn"
type = "function"

[[extensions.targeting]]
target = "cart.lines.discounts.generate.run"
input_query = "src/cart_lines_discounts_generate_run.graphql"
export = "cart_lines_discounts_generate_run"

[extensions.build]
command = "cargo build --target=wasm32-wasip1 --release"
path = "target/wasm32-wasip1/release/volume-discount-fn.wasm"
watch = ["src/**/*.rs"]

Étape 1.2 : La requête d'entrée (src/cart_lines_discounts_generate_run.graphql)


query Input {
  cart {
    lines {
      id
      quantity
      cost {
        subtotalAmount {
          amount
        }
      }
      merchandise {
        ... on ProductVariant {
          product {
            inAnyCollection(ids: ["gid://shopify/Collection/123456789"])
          }
        }
      }
    }
  }
  discount {
    discountClasses
  }
}

Conseil : Les Functions ne voient que les données que vous demandez. Gardez le GraphQL minimal — chaque champ omis permet une exécution plus rapide et moins coûteuse.

Étape 1.3 : La logique (src/cart_lines_discounts_generate_run.rs)


use super::schema;
use shopify_function::prelude::*;
use shopify_function::Result;

#[shopify_function]
fn cart_lines_discounts_generate_run(
    input: schema::cart_lines_discounts_generate_run::Input,
) -> Result<schema::CartLinesDiscountsGenerateRunResult> {
    // Sortie si la classe de remise ne correspond pas
    let has_order_discount = input
        .discount()
        .discount_classes()
        .contains(&schema::DiscountClass::Order);

    if !has_order_discount {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Somme des quantités d'articles de la collection cible
    let qualifying_qty: i64 = input
        .cart()
        .lines()
        .iter()
        .filter(|line| {
            if let schema::Merchandise::ProductVariant(v) = line.merchandise() {
                *v.product().in_any_collection()
            } else {
                false
            }
        })
        .map(|line| *line.quantity())
        .sum();

    if qualifying_qty < 5 {
        return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] });
    }

    // Appliquer 10 % de réduction sur le sous-total de la commande
    Ok(schema::CartLinesDiscountsGenerateRunResult {
        operations: vec![schema::CartOperation::OrderDiscountsAdd(
            schema::OrderDiscountsAddOperation {
                selection_strategy: schema::OrderDiscountSelectionStrategy::First,
                candidates: vec![schema::OrderDiscountCandidate {
                    targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal(
                        schema::OrderSubtotalTarget {
                            excluded_cart_line_ids: vec![],
                        },
                    )],
                    message: Some("Volume discount: 10% off".to_string()),
                    value: schema::OrderDiscountCandidateValue::Percentage(
                        schema::Percentage { value: Decimal(10.0) }
                    ),
                    conditions: None,
                    associated_discount_code: None,
                }],
            },
        )],
    })
}

Étape 1.4 : Tester, déployer, activer


# Développement local avec rechargement à chaud
shopify app dev

# Une fois prêt, déployez
shopify app deploy

# Dans le panneau GraphiQL qui s'ouvre (appuyez sur `g` dans le terminal de dev),
# créez la remise automatique qui utilise votre Function :
mutation {
  discountAutomaticAppCreate(
    automaticAppDiscount: {
      title: "Volume Discount (5+ collection items)"
      functionHandle: "volume-discount-fn"
      discountClasses: [ORDER]
      startsAt: "2026-04-16T00:00:00Z"
    }
  ) {
    automaticAppDiscount { discountId }
    userErrors { field message }
  }
}

C'est tout. La Function est active, soumise au contrôle de version et remplace complètement l'ancien Script.

Tutoriel 2 : Remplacer un Shipping Script (Masquer une méthode au-dessus d'un seuil de panier)

Un Script classique : « Masquer la livraison Express lorsque le sous-total du panier dépasse 500 $ pour éviter des envois urgents coûteux sur de grosses commandes ». Voici la version Function de type Delivery Customization.

Étape 2.1 : Génération du code


shopify app generate extension --template delivery_customization --name hide-express-fn

Étape 2.2 : Requête d'entrée (src/run.graphql)


query Input {
  cart {
    cost {
      subtotalAmount {
        amount
      }
    }
    deliveryGroups {
      deliveryOptions {
        handle
        title
      }
    }
  }
}

Étape 2.3 : Logique (src/run.js — variante JavaScript)


// @ts-check
/**
 * @typedef {import("../generated/api").RunInput} RunInput
 * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult
 */

const NO_CHANGES = { operations: [] };
const THRESHOLD = 500.0;
const HIDE_TITLES = ["Express", "Overnight"];

/**
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const subtotal = parseFloat(input.cart.cost.subtotalAmount.amount);
  if (subtotal < THRESHOLD) return NO_CHANGES;

  const operations = input.cart.deliveryGroups.flatMap((group) =>
    group.deliveryOptions
      .filter((opt) => HIDE_TITLES.some((t) => opt.title.includes(t)))
      .map((opt) => ({
        hide: { deliveryOptionHandle: opt.handle },
      }))
  );

  return { operations };
}

Étape 2.4 : Activation via l'Admin (aucune mutation GraphQL requise)

Les Delivery Customizations disposent d'une interface d'administration intégrée. Après shopify app deploy :

  1. Allez dans Settings → Shipping and delivery

  2. Faites défiler jusqu'à la section Customizations en bas

  3. Cliquez sur Add customization → sélectionnez votre Function

  4. Enregistrez

La règle de masquage est active en production. Aucune mutation requise.



Shopify delivery customization Function hiding shipping option at checkout

Tutoriel 3 : Remplacer un Payment Script (Masquer le paiement à la livraison pour le B2B)

Ancien Script : « Masquer le paiement à la livraison pour tout client ayant le tag 'B2B' ». Voici la version Payment Customization.

Étape 3.1 : Génération du code


shopify app generate extension --template payment_customization --name hide-cod-b2b-fn

Étape 3.2 : Requête d'entrée


query Input {
  cart {
    buyerIdentity {
      customer {
        hasTags(tags: [{ tag: "B2B" }]) {
          tag
          hasTag
        }
      }
    }
  }
  paymentMethods {
    id
    name
  }
}

Étape 3.3 : Logique (src/run.js)


const NO_CHANGES = { operations: [] };

export function run(input) {
  const tagCheck = input.cart?.buyerIdentity?.customer?.hasTags?.[0];
  const isB2B = tagCheck?.hasTag === true;
  if (!isB2B) return NO_CHANGES;

  const codMethod = input.paymentMethods.find((pm) =>
    pm.name.toLowerCase().includes("cash on delivery")
  );
  if (!codMethod) return NO_CHANGES;

  return {
    operations: [{ hide: { paymentMethodId: codMethod.id } }],
  };
}

Étape 3.4 : Activation

Les Payment Customizations disposent également d'une interface d'administration sous Settings → Payments → Customizations. Même processus que pour la livraison — sélectionnez votre Function, enregistrez, terminé.

Puisque vous lisez ceci — Un mot sur le post-achat

Une brève mise au point puisque vous êtes sur le blog de Revize. Revize gère ce que les Functions ne peuvent pas toucher — une fois la commande passée, les clients veulent ajouter un article, changer de taille, corriger l'adresse de livraison ou appliquer une remise oubliée. Les Functions interviennent lors du passage à la caisse. Revize intervient après. Les Functions déterminent ce qui est autorisé dans le panier ; Revize permet à vos clients et à votre équipe support de modifier la commande après coup sans passer par un cycle d'annulation et de réédition. Cela compte pour deux types de boutiques : celles avec un volume de commandes tel que la modification manuelle devient impossible (les boutiques Plus, évidemment, mais aussi les boutiques Advanced à fort trafic), et celles dont l'image de marque repose sur l'expérience client — où un e-mail indiquant « désolé, nous ne pouvons pas modifier cela » nuit à la fidélisation.

Si votre plan de migration prévoit de passer des Scripts aux Functions mais que vous n'avez pas encore résolu la modification des commandes post-achat, vous vous heurterez rapidement à un autre obstacle. Le guide de gestion des commandes que nous venons de publier présente l'ensemble des bonnes pratiques post-achat.

Revenons à la migration.

Stratégie de test : La méthode des clients taggués

Les Functions n'ont pas de « mode brouillon » activable dans l'admin. La méthode professionnelle consiste à conditionner la nouvelle Function à un tag client, à exécuter l'ancien Script et la nouvelle Function en parallèle, à vérifier qu'ils produisent un résultat identique pour les utilisateurs taggués, puis à basculer définitivement.

Étape 1 : Taguez vos utilisateurs de test

Dans Customers, ajoutez le tag FN-TESTER à deux ou trois comptes internes.

Étape 2 : Conditionner la Function à la présence du tag


// Au début de votre fonction run
let is_tester = input
    .cart()
    .buyer_identity()
    .and_then(|bi| bi.customer())
    .map(|c| c.has_any_tag())
    .unwrap_or(&false);

if !*is_tester {
    return Ok(default_result);  // Passage à l'ancien Script existant
}

// La logique de la nouvelle Function s'exécute uniquement pour les utilisateurs taggués

Étape 3 : Ajoutez hasAnyTag à votre requête d'entrée


cart {
  buyerIdentity {
    customer {
      hasAnyTag(tags: ["FN-TESTER"])
    }
  }
}

Étape 4 : Vérifier dans le processus d'achat

Connectez-vous avec un compte taggué, passez commande, confirmez que la Function s'active. Connectez-vous avec un compte non taggué, confirmez que l'ancien Script s'exécute toujours. Une fois la parité validée sur quelques jours, retirez la vérification du tag pour appliquer la Function à tous.

Étape 5 : Désactiver l'ancien Script

Allez dans Apps → Script Editor → [Votre Script] → Unpublish. Une fois désactivé, la Function devient la seule source de vérité.

Workflow de déploiement évolutif

Ne déployez pas indéfiniment depuis l'ordinateur d'un développeur. Une fois un ou deux Scripts migrés, configurez un véritable pipeline CI.

Le workflow minimal viable


# .github/workflows/deploy-functions.yml
name: Deploy Shopify Functions
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - uses: dtolnay/rust-toolchain@stable
        with: { targets: wasm32-wasip1 }
      - run: npm install -g @shopify/cli@latest
      - run: shopify app deploy --force
        env:
          SHOPIFY_CLI_PARTNERS_TOKEN: ${{ secrets.SHOPIFY_CLI_PARTNERS_TOKEN }}

Générez le jeton de partenaire depuis votre tableau de bord Partner sous Settings → Tokens. Désormais, chaque fusion sur main déploie vos Functions. Fini les discussions sur Slack pour savoir qui a déployé la dernière version.

Gestion des versions et retour arrière

shopify app deploy crée un instantané versionné. Pour revenir en arrière :


shopify app versions list
shopify app release --version <previous-version-id

Par rapport aux Scripts — où le retour arrière nécessitait de retrouver l'ancien code pour le recoller — la différence est radicale.



Shopify Functions deployment pipeline across local staging and production environments

Ce que la plupart des équipes ratent

Après avoir accompagné des marchands Plus dans cette migration l'année passée, les cinq mêmes erreurs reviennent systématiquement.

1. Traiter les Functions comme une simple copie conforme des Scripts. Ce n'est pas le cas. Une seule Function peut remplacer trois Scripts grâce à une logique d'embranchement plus propre. Analysez vos Scripts de manière globale avant de réécrire.

2. Oublier les scopes de lecture. De nombreuses Functions requièrent read_customers, read_orders ou write_discounts. Ajoutez-les dans shopify.app.toml sous scopes et ré-autorisez l'application, sinon votre requête d'entrée renverra null.

3. Lancer les Functions sur des clients non taggués sans test de parité. Même si votre code semble correct, des cas limites (panier vide, cartes-cadeaux, avoirs de boutique, brouillons B2B) révéleront des failles. Un déploiement progressif avec tag vous prend deux jours de plus mais vous évite une panne critique.

4. Ignorer le Customizations Report. C'est le meilleur inventaire de ce qui s'exécute réellement sur votre boutique. Ne migrez pas de mémoire — basez-vous sur ce rapport.

5. Hardcoder les IDs de collection et les tags clients. Utilisez la configuration de Function via les metafields si vous avez besoin de valeurs ajustables par le marchand. La CLI peut générer des configurations basées sur les metafields — consultez la documentation de Shopify à ce sujet.

Plan d'action pour les 75 prochains jours

Un planning réaliste pour aborder sereinement l'échéance du 30 juin.


Semaine

Action

Semaine 1 (cette semaine)

Consulter le Customizations Report. Inventorier chaque Script. Décider entre Function, application publique ou suppression.

Semaines 2–3

Configurer l'environnement de développement local. Générer la première Function. Migrer le Script le plus simple (généralement une règle de masquage de paiement).

Semaines 4–6

Migrer les Scripts de remise. Ce sont ceux qui prennent le plus de temps car la Discounts API est la plus complète. Réaliser des tests approfondis par tag.

Semaines 7–8

Migrer les Scripts de livraison. Activer les Delivery Customizations via l'Admin.

Semaines 9–10

Configurer le pipeline CI. Automatiser tous les déploiements.

Semaine 11 (mi-juin)

Vérification finale de parité. Désactiver tous les Scripts. Faire tourner la boutique uniquement avec les Functions pendant deux semaines.

30 juin

Date butoir. Tout fonctionne car vous avez terminé en avance.

Si vous commencez cette semaine, vous conservez une marge de sécurité. Si vous commencez en juin, vous n'en aurez pas.



Week-by-week migration roadmap from Shopify Scripts to Functions

Foire Aux Questions

Ai-je besoin de Shopify Plus pour utiliser les Functions?

Les Functions personnalisées nécessitent Shopify Plus, mais les Functions issues d'applications publiques fonctionnent sur tous les forfaits. Si vous n'êtes pas sur Plus, deux choix s'offrent à vous : installer une application publique depuis le Shopify App Store qui déploie la Function pour vous, ou passer à Plus pour coder vos propres Functions personnalisées. La plupart des grands marchands utilisant des Scripts possédaient déjà Plus, ce qui ne change presque rien en pratique.

Puis-je écrire des Functions en TypeScript?

Oui — TypeScript est entièrement pris en charge et la CLI le configure pour vous. Lorsque vous lancez shopify app generate extension et choisissez « JavaScript », le projet généré inclut les déclarations de types de import("../generated/api"). Vous pouvez renommer les fichiers en .ts et ajouter un tsconfig.json si vous préférez. Le fichier compilé final (WASM) est strictement identique quel que soit le langage source.

Quelle est la rapidité des Functions par rapport aux Scripts?

Les Functions s'exécutent généralement en moins de 5 ms — soit nettement plus vite que les Scripts Ruby. Comme elles sont compilées en WebAssembly et s'exécutent dans un environnement restreint, Shopify impose une limite d'exécution de 5 ms. Si votre Function la dépasse, l'opération est abandonnée et la Function ne renvoie rien. En pratique, une Function bien conçue nécessite 1 à 2 ms. Les performances sont bien supérieures à celles des Scripts.

Une Function peut-elle appeler une API externe?

Non — les Functions ne peuvent pas effectuer de requêtes réseau. Il s'agit uniquement de calcul pur : données du panier en entrée → opérations en sortie. Si vous avez besoin de données externes (recherche CRM, vérification d'inventaire en temps réel), vous devez soit stocker ces données dans des metafields au préalable, soit utiliser une autre méthode (App Proxy, webhooks, Cart Transform avec appel back-end). C'est la raison la plus fréquente pour laquelle les équipes doivent repenser l'architecture plutôt que de faire un simple portage.

Quelle est la différence entre Cart Transform et les remises?

Les remises modifient les prix, tandis que Cart Transform modifie le contenu du panier. Utilisez la Discounts API pour appliquer un rabais de 10 %, offrir la livraison ou proposer une offre de type BOGO. Utilisez Cart Transform pour regrouper deux produits en un seul article, ou diviser une variante en plusieurs. De nombreux anciens Scripts mélangeaient ces deux aspects — lors de la migration, séparez-les en deux Functions distinctes.

Comment tester une Function localement sans boutique de développement?

Vous pouvez exécuter des tests unitaires avec cargo test (Rust) ou npm test (JS), mais les tests d'intégration complets requièrent une boutique de développement. La CLI propose shopify app function run qui exécute votre Function avec un fichier d'entrée de test — idéal pour itérer rapidement. Mais pour valider le comportement final du passage à la caisse de bout en bout, vous avez besoin d'une véritable boutique avec un panier réel.

Puis-je avoir plusieurs Functions du même type?

Oui — Shopify prend en charge plusieurs Functions par cible, et elles s'exécutent dans un ordre déterminé. Pour les remises, l'ordre est régi par les règles de cumul de Shopify. Pour les Delivery et Payment Customizations, vous pouvez chaîner les Functions, la sortie de l'une alimentant l'entrée de la suivante. La plupart des équipes utilisent une seule Function par type pour simplifier la gestion.

Qu'advient-il de mon Script après le déploiement de la Function?

Les deux s'exécutent en parallèle jusqu'à ce que vous désactiviez le Script dans Apps → Script Editor. Cela est intentionnel et vous permet de réaliser vos tests en conditions réelles. Après validation de la Function, désactivez manuellement le Script. Après le 30 juin 2026, tous les Scripts cesseront de s'exécuter, qu'ils soient désactivés ou non.

La migration aura-t-elle un impact sur mon SEO ou mon thème?

Non — les Functions s'exécutent côté serveur lors du passage à la caisse et n'interfèrent jamais avec votre thème ou vos pages produits. Elles modifient uniquement les remises, les options de livraison et les méthodes de paiement lors du paiement. Votre boutique en ligne, vos fiches produits et votre SEO restent inchangés.

Comment migrer un Script qui utilise Input.line_items avec des propriétés personnalisées?

Les propriétés personnalisées sont accessibles via le champ attribute des lignes du panier dans l'entrée GraphQL. Ajoutez attribute(key: "votre-cle") { value } dans la sélection lines. La Function les lit de la même manière que les Scripts lisaient les propriétés d'articles, mais via GraphQL plutôt que par des appels de méthodes Ruby.

Qu'en est-il des analyses de données et des tags de commande? Les Functions peuvent-elles écrire des données?

Les Functions ne peuvent pas écrire de tags de commande ni déclencher de webhooks — elles renvoient uniquement des opérations sur le panier en cours. Pour le taggage ou les flux de travail en aval, utilisez Shopify Flow déclenché par l'événement de création de commande. De nombreux marchands associent une Function (pour la remise) à un Flow (pour ajouter le tag « VOLUME-DISCOUNT-APPLIED » sur la commande).

Existe-t-il une application publique que je peux installer au lieu de développer une Function personnalisée?

Oui — le Shopify App Store propose des dizaines d'applications qui intègrent des Functions pour les cas d'usage courants. Recherchez « discount function », « delivery customization » ou « payment customization ». Pour des besoins classiques (remises sur volume, masquage de paiement par tag, livraison gratuite dès X $), une application existante peut vous éviter des jours de développement. Réservez les Functions personnalisées aux logiques réellement spécifiques à votre activité.

Que se passe-t-il si je dépasse la date limite du 30 juin?

Le Script s'arrête — il n'y a pas de solution de repli, pas de période de grâce et aucun report possible. Quelle que soit la fonction du Script (remise, masquage de tarif de livraison, blocage de paiement), le comportement par défaut sera rétabli à minuit UTC le 1er juillet. Si votre activité dépend de cette logique, prévoyez d'être opérationnel bien avant cette date. La migration prend généralement plus de temps que prévu, notamment en raison des tests de parité.

Puis-je supprimer définitivement l'application Script Editor?

Vous pourrez la désinstaller après le 30 juin 2026, mais Shopify la retirera probablement d'office. Une fois que les Scripts ne s'exécutent plus, l'éditeur n'a plus d'utilité. Vous pouvez également désactiver tous vos Scripts dès maintenant et désinstaller l'application immédiatement si votre migration est terminée — vos Functions fonctionnent de manière autonome.

Ce qu'il faut faire cette semaine

Ne vous contentez pas de lire cet article. Réalisez ces quatre actions dans les sept prochains jours.

1. Récupérer le Customizations Report. Allez dans Settings → Checkout → Customizations Report. Exportez-le. C'est votre base de travail pour la migration.

2. Configurer votre environnement de dev. Installez Node 18+, la Shopify CLI et Rust (si nécessaire). Vérifiez que shopify version fonctionne. Durée estimée : 30 minutes.

3. Générer et déployer une petite Function sur une boutique de dev. Choisissez le Script le plus simple — souvent une règle de masquage de paiement. Migrez-le de bout en bout. Même s'il ne va pas en production, vous aurez validé votre environnement de travail.

4. Bloquer des créneaux dans votre calendrier pour les huit prochaines semaines. Une migration ne se fait pas à la va-vite entre deux tâches quotidiennes. Réservez des plages régulières — par exemple chaque mardi et jeudi après-midi — et traitez ce projet comme une priorité absolue.

Parmi les équipes que nous avons accompagnées, le schéma reste le même : deux semaines d'attente, trois semaines de développement réel, une semaine de finalisation. Cela représente six semaines. Il vous en reste dix. Profitez de cette marge pour la revue de code et l'assurance qualité, sans repousser le lancement du projet.

Et une fois la logique de paiement opérationnelle, l'étape suivante pour la plupart des marchands est le post-achat — modifications d'adresses, échanges d'articles ou ajouts de remises après commande. Si cela fait partie de vos projets (et cela devrait être le cas, que vous soyez un marchand Plus à fort volume ou une boutique Advanced axée sur l'expérience client), Revize est disponible sur le Shopify App Store et fonctionne en parfaite synergie avec toutes les Functions que vous développerez.

Ressources


Articles connexes


Mis à jour en août 2026. Revize est une application Shopify permettant aux clients de modifier eux-mêmes leurs commandes après l'achat. Elle permet aux acheteurs de modifier leur adresse de livraison, d'échanger une variante ou un produit, d'annuler et d'obtenir un remboursement ou un avoir avant le traitement de la commande, le tout sans ouvrir de ticket d'assistance. En savoir plus sur la possibilité de permettre aux clients de modifier leurs propres commandes Shopify, ou retrouver Revize sur le Shopify App Store.

Repensez votre boutique Shopify. Misez sur l’expérience client.

© Copyright 2024, Tous droits réservés

Repensez votre boutique Shopify. Misez sur l’expérience client.

© Copyright 2024, Tous droits réservés

Repensez votre boutique Shopify. Misez sur l’expérience client.

© Copyright 2024, Tous droits réservés

Repensez votre boutique Shopify. Misez sur l’expérience client.

© Copyright 2024, Tous droits réservés