Skip to main content

Build the delivery options function

With Shopify Functions, you can customize delivery options. This allows you to hide, reorder, or rename the delivery options available to buyers at checkout. This tutorial demonstrates how to use Shopify Functions to rename a checkout delivery option based on shipping destination.


In this tutorial, you'll learn how to do the following tasks:

  • Generate starter code for Shopify Functions.
  • Use GraphQL to define the input of your function.
  • Deploy functions to the Shopify platform.
  • Review logs for your function.
Screenshot that shows a renamed delivery option

  • You're using API version 2025-07 or higher for your function.

Anchor to Rust-specific requirementsRust-specific requirements

The following requirements are specific to Rust-based development with Shopify Functions.

  • You've installed Rust.

    On Windows, Rust requires the Microsoft C++ Build Tools. Make sure to select the Desktop development with C++ workload when installing the tools.

  • You've installed the wasm32-wasip1 target:

    Terminal

    rustup target add wasm32-wasip1

  • In the Delivery Customization API, the carrier name is automatically prepended to the shipping method title at checkout when using the DeliveryOptionRenameOperation object, and can't be altered or omitted through the API. For example, if the carrier name is UPS and the method is Standard, you could change UPS Standard to UPS Standard Shipping, but you couldn't change UPS Standard to Standard Shipping.

If you want to quickly get started, then you can get the sample code by completing the following steps. This tutorial describes the sample code step by step.

  1. Clone the delivery customizations sample app:

    Terminal

    shopify app init --template https://github.com/Shopify/function-examples/sample-apps/delivery-customizations
  1. Enter a name for your app project.

  2. Navigate to your app directory:

Terminal

cd <directory>
  1. Link your app configuration:

Terminal

shopify app config link
  1. Start a local server for your app:

Terminal

shopify app dev
  1. With the server running, open the Preview URL in the terminal output.

    When you open the URL, you're prompted to install the app on your development store.

  2. Click Install app to install the app on the store.

  1. Create and test your delivery customization.

Anchor to Step 1: Create the delivery customization functionStep 1: Create the delivery customization function

To create your delivery customization function, you can use Shopify CLI to generate a starter function, specify the inputs for your function using an input query, and implement your function logic using JavaScript or Rust.

  1. Navigate to your app directory:

    Terminal

    cd <directory>
  2. Run the following command to create a new delivery customization extension:

    Terminal

    shopify app generate extension --template delivery_customization --name delivery-customization
  1. Choose the language that you want to use. For this tutorial, you should select either Rust or JavaScript.

    Shopify defaults to Rust as the most performant and recommended language choice to stay within the platform limits. For more information, refer to language considerations.

    Terminal

    ? What would you like to work in?
    > (1) Rust
    (2) JavaScript
    (3) TypeScript
    (4) Wasm
  1. Navigate to extensions/delivery-customization:

    Terminal

    cd extensions/delivery-customization
  2. Replace the contents of src/run.graphql file with the following code.

    run.graphql defines the input for the function. You need the cart delivery groups, with the delivery state/province code and available delivery options.

    The query differs slightly in Rust and JavaScript due to code generation requirements.

    run.graphql

    src/run.graphql

    query Input {
    cart {
    deliveryGroups {
    deliveryAddress {
    provinceCode
    }
    deliveryOptions {
    handle
    title
    }
    }
    }
    }
    query RunInput {
    cart {
    deliveryGroups {
    deliveryAddress {
    provinceCode
    }
    deliveryOptions {
    handle
    title
    }
    }
    }
    }
  3. If you're using JavaScript, then run the following command to regenerate types based on your input query:

    Terminal

    shopify app function typegen
  4. Replace the src/run.rs or src/run.js file with the following code.

    This function logic appends a message to all delivery options if the shipping address state or province code is NC. You can adjust this to the state or province of your choice.

    File

    src/run.rs

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

    #[shopify_function]
    fn run(input: schema::run::Input) -> Result<schema::CartDeliveryOptionsTransformRunResult> {
    let message = "May be delayed due to weather conditions";

    let operations = input
    .cart()
    .delivery_groups()
    .iter()
    .filter_map(|group| {
    if let Some(address) = group.delivery_address() {
    if address.province_code() == Some(&"NC".to_string()) {
    return Some(
    group.delivery_options().iter().map(|option| {
    schema::Operation::Rename(schema::DeliveryOptionRenameOperation {
    delivery_option_handle: option.handle().to_string(),
    title: match option.title() {
    Some(title) => format!("{} - {}", title, message),
    None => message.to_string(),
    },
    })
    })
    .collect::<Vec<_>>(),
    );
    }
    }
    None
    })
    .flatten()
    .collect();

    Ok(schema::FunctionRunResult { operations })
    }
    // @ts-check

    // Use JSDoc annotations for type safety
    /**
    * @typedef {import("../generated/api").RunInput} RunInput
    * @typedef {import("../generated/api").CartDeliveryOptionsTransformRunResult} CartDeliveryOptionsTransformRunResult
    * @typedef {import("../generated/api").Operation} Operation
    */

    // The configured entrypoint for the 'cart.delivery-options.transform.run' extension target
    /**
    * @param {RunInput} input
    * @returns {CartDeliveryOptionsTransformRunResult}
    */
    export function run(input) {
    // The message to be added to the delivery option
    const message = "May be delayed due to weather conditions";

    let toRename = input.cart.deliveryGroups
    // Filter for delivery groups with a shipping address containing the affected state or province
    .filter(group => group.deliveryAddress?.provinceCode &&
    group.deliveryAddress.provinceCode == "NC")
    // Collect the delivery options from these groups
    .flatMap(group => group.deliveryOptions)
    // Construct a rename operation for each, adding the message to the option title
    .map(option => /** @type {Operation} */({
    deliveryOptionRename: {
    deliveryOptionHandle: option.handle,
    title: option.title ? `${option.title} - ${message}` : message
    }
    }));

    // The @shopify/shopify_function package applies JSON.stringify() to your function result
    // and writes it to STDOUT
    return {
    operations: toRename
    };
    };

Anchor to Step 2: Preview the function on a development storeStep 2: Preview the function on a development store

To test your function, you need to make it available to your development store.

  1. If you're developing a function in a language other than JavaScript or TypeScript, ensure you have configured build.watch in your function extension configuration.
  1. Navigate back to your app root:

    Terminal

    cd ../..
  1. Use the Shopify CLI dev command to start app preview:

    Terminal

    shopify app dev

    You can keep the preview running as you work on your function. When you make changes to a watched file, Shopify CLI rebuilds your function and updates the function extension's drafts, so you can immediately test your changes.

  2. Follow the CLI prompts to preview your app, and install it on your development store.


Anchor to Step 3: Create the delivery customization with GraphiQLStep 3: Create the delivery customization with GraphiQL

To activate your function, you must create a delivery customization on the store where you installed your app. You can do this using the deliveryCustomizationCreate GraphQL mutation.

In subsequent tutorials, you'll use metafields on this delivery customization to configure your function, and create a user interface so merchants can configure the function themselves.

  1. Install the Shopify GraphiQL app on your store. If you've already installed GraphiQL, then you should do so again to select the necessary access scopes for delivery customizations.

    Note

    Make sure to select the read_delivery_customizations and write_delivery_customizations access scopes for the Admin API.

  2. In the GraphiQL app, in the API Version field, select the 2025-07 version.

  1. Find the ID of your function by executing the following query:

    find-function-query.graphql

    query {
    shopifyFunctions(first: 25) {
    nodes {
    app {
    title
    }
    apiType
    title
    id
    }
    }
    }

    The result contains a node with your function's ID:

    find-function-result.json

    {
    "app": {
    "title": "your-app-name-here"
    },
    "apiType": "delivery_customization",
    "title": "delivery-customization",
    "id": "YOUR_FUNCTION_ID_HERE"
    }
  1. Execute the following mutation and replace YOUR_FUNCTION_ID_HERE with the ID of your function:

    mutation.graphql

    mutation {
    deliveryCustomizationCreate(deliveryCustomization: {
    functionId: "YOUR_FUNCTION_ID_HERE"
    title: "Add message to delivery options for state/province"
    enabled: true
    }) {
    deliveryCustomization {
    id
    }
    userErrors {
    message
    }
    }
    }

    You should receive a GraphQL response that includes the ID of the created delivery customization. If the response includes any messages under userErrors, then review the errors, check that your mutation and functionId are correct, and try the request again.

    Tip

    If you receive a Could not find Function error, then confirm the following:


Anchor to Step 4: Test the delivery customizationStep 4: Test the delivery customization

  1. From the Shopify admin, go to Settings > Shipping and delivery.
  2. Check the Delivery customizations section. You should find the Add message to delivery options for state/province delivery customization that you created with GraphiQL.
  1. Open your development store, build a cart, and proceed to checkout.
  2. Enter a delivery address that doesn't use the specified state/province code. You shouldn't see any additional messaging on the delivery options.
  3. Change your shipping address to use your chosen state/province code. Your delivery options should now have the additional messaging.
  1. Open your terminal where shopify app dev is running, and review your function executions.

    When testing functions on development stores, the output of dev includes executions of your functions, any debug logging you have added to them, and a link to a local file with the full function execution details.

  2. In a new terminal window, use the Shopify CLI app function replay command to replay a function execution locally, and debug your function without the need to re-trigger the function execution on Shopify.

Terminal

shopify app function replay
  1. Select the function execution from the top of the list. Press q to quit when you are finished debugging.


Was this page helpful?