How to make a Shopify Function only run at checkout

Topic summary

A developer created a Shopify cart and checkout validation function to require first name, last name, and phone number fields. This workaround is necessary because Shopify B2B’s “ship to any address” feature overrides native admin settings for required fields.

Core Problem:
The validation function runs during all cart actions (like adding products), not just at checkout. This causes errors for logged-in customers without complete profile information when they simply add items to their cart.

Attempted Solutions:
The developer tried using conditionals to detect checkout context by checking for deliveryAddress, deliveryOptions, and selectedDeliveryOption, but these properties are accessible before checkout as well.

Current Configuration:

  • Extension type: purchase.validation.run function
  • Target: Cart and checkout validation
  • The validation logic checks delivery address fields (firstName, lastName, phone) and returns localized error messages when fields are empty

Open Question:
Seeking a method to restrict function execution exclusively to the checkout step, preventing it from triggering during earlier cart interactions.

Summarized with AI on November 4. AI used: claude-sonnet-4-5-20250929.

I have a Shopify function created, as a cart and checkout validation extension. It’s attempting to require first name, last name, and phone number input fields. I know there’s a native way to do this in the Shopify admin settings, however, if you enable ship to any address in Shopify B2B, it overrides this setting.

The issue with the function is that it’s running at other cart actions, outside of checkout. This poses an issue when the customer is logged in, and they don’t have a first name or phone number associated with them, and it throws the error when adding a product to the cart.

I have tried adding various conditionals in my run.js file, such as checking for deliveryAddress, deliveryOptions, selectedDeliveryOption, etc, as a way of determining whether we’re at the checkout step, however, all of them are also returned/accessible before checkout for some reason.

Is there a way to make this function only execute at checkout?

You can see my shopify.extension.toml below:

api_version = "2024-10"

[[extensions]]
name = "t:name"
handle = "required-input-field-validations"
type = "function"

description = "t:description"

  [[extensions.targeting]]
  target = "purchase.validation.run"
  input_query = "src/run.graphql"
  export = "run"

  [extensions.build]
  command = ""
  path = "dist/function.wasm"

Here is my run.js file:

// @ts-check

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

/**
 * The entry point for the Shopify Function
 *
 * @param {RunInput} input
 * @returns {FunctionRunResult}
 */
export function run(input) {
  const errors = [];

  // Access delivery address information from the input
  const deliveryGroups = input.cart.deliveryGroups || [];
  const deliveryAddress = deliveryGroups[0]?.deliveryAddress || {};

  const firstName = deliveryAddress.firstName || '';
  const lastName = deliveryAddress.lastName || '';
  const phone = deliveryAddress.phone || '';

  // Debugging logs
  console.log('First Name:', firstName);
  console.log('Last Name:', lastName);
  console.log('Phone:', phone);

  // Validate First Name
  if (!firstName.trim()) {
    errors.push({
      localizedMessage: 'Please enter your first name.',
      target: 'deliveryAddressFirstName',
    });
  }

  // Validate Last Name
  if (!lastName.trim()) {
    errors.push({
      localizedMessage: 'Please enter your last name.',
      target: 'deliveryAddressLastName',
    });
  }

  // Validate Phone Number
  if (!phone.trim()) {
    errors.push({
      localizedMessage: 'Please enter your phone number.',
      target: 'deliveryAddressPhone',
    });
  }

  return { errors };
}

Thank you.