Add review requirement
A review requirement enables you to control whether an order is submitted as a draft for review. This tutorial shows you how to use the orderReviewAdd
operation in the Payment Customization API to dynamically add a review requirement during checkout based on business rules.
Anchor to What you'll learnWhat you'll learn
In this tutorial, you'll learn foundational concepts and techniques for customizing checkout behaviour using Shopify Functions and the Payment Customization API.
- How to query and use cart data in a function's input to drive decisions.
- Conditionally using operations (such as
orderReviewAdd
) to modify checkout flows, including creating draft orders for review. - Testing and validating function logic in development environments.

Anchor to RequirementsRequirements
- You've completed at least the first tutorial in this series.
Anchor to Step 1: Configure the functionStep 1: Configure the function
First, start a developement server if you haven't already (see CLI reference):
terminal
In this example, a review requirement is added based on the cart total. You'll implement the following behaviour:
- No review is required for any order where the cart total is less than $5000.
- If the cart total is $5000 or more:
- B2B orders will checkout as a Draft Order.
- D2C orders aren't affected (see limitations).
-
Navigate to your function in
extensions/payment-customization
:Terminal
cd extensions/payment-customization -
Replace the code in the
src/run.graphql
file with the following code.The input query retrieves the
cart
object, which includes acost
object with the total value of the cart.The query differs slightly in Rust and JavaScript due to code generation requirements.
run.graphql
src/run.graphql
query Input {cart {cost {totalAmount {amount}}}}query RunInput {cart {cost {totalAmount {amount}}}}query Input { cart { cost { totalAmount { amount } } } }
query RunInput { cart { cost { totalAmount { amount } } } }
-
If you're using JavaScript, then run the following command to regenerate types based on your input query:
Terminal
shopify app function typegen -
Implement business logic for the function to add a review requirement when the cart total exceeds $5000. Replace the contents of
src/run.rs
orsrc/run.js
file with the following code:File
src/run.rs
use crate::schema;use shopify_function::prelude::*;use shopify_function::Result;fn cart_payment_methods_transform_run(input: schema::cart_payment_methods_transform_run::Input) -> Result<schema::CartPaymentMethodsTransformRunResult> {let cart_total: f64 = input.cart().cost().total_amount().amount().as_f64();let operations = if cart_total > 5000.0 {vec![schema::Operation::OrderReviewAdd(schema::OrderReviewAddOperation {reason: "An order over $5000 requires review.".to_string()})]} else {vec![]};Ok(schema::CartPaymentMethodsTransformRunResult { operations })}// @ts-check/*** @typedef {import("../generated/api").RunInput} RunInput* @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult*//*** @type {FunctionRunResult}*//*** Sets payment terms based on cart total and buyer identity* @param {RunInput} input - Function input* @returns {FunctionRunResult} Function result with operations to apply*/export function run(input) {const operations = [];const totalAmount = input.cart.cost.totalAmount.amount;if (totalAmount > 5000) {operations.push({orderReviewAdd: {reason: "An order over $5000 requires review."}});}return { operations };}use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_payment_methods_transform_run(input: schema::cart_payment_methods_transform_run::Input) -> Result<schema::CartPaymentMethodsTransformRunResult> { let cart_total: f64 = input.cart().cost().total_amount().amount().as_f64(); let operations = if cart_total > 5000.0 { vec![schema::Operation::OrderReviewAdd( schema::OrderReviewAddOperation { reason: "An order over $5000 requires review.".to_string() } )] } else { vec![] }; Ok(schema::CartPaymentMethodsTransformRunResult { operations }) }
// @ts-check /** * @typedef {import("../generated/api").RunInput} RunInput * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult */ /** * @type {FunctionRunResult} */ /** * Sets payment terms based on cart total and buyer identity * @param {RunInput} input - Function input * @returns {FunctionRunResult} Function result with operations to apply */ export function run(input) { const operations = []; const totalAmount = input.cart.cost.totalAmount.amount; if (totalAmount > 5000) { operations.push({ orderReviewAdd: { reason: "An order over $5000 requires review." } }); } return { operations }; }
Anchor to Step 2: Test the payment customizationStep 2: Test the payment customization
Test how the review requirement is added based on the cart total.
Anchor to Test with a B2B checkout with a cart total under $5000Test with a B2B checkout with a cart total under $5000
- Open your development store and log in as a B2B customer.
- Build a cart with a total (including shipping and tax) under $5000.
- The review requirement threshold is not met in this scenario. Verify that the function does not add a review requirement.
- Complete the checkout and verify an order is created.

Anchor to Test with a B2B checkout with a cart total over $5000Test with a B2B checkout with a cart total over $5000
- Open your development store and log in as a B2B customer.
- Build a cart with a total (including shipping and tax) over $5000.
- Since the review requirement threshold is met, verify that the function adds a review requirement.
- Submit the checkout for review and verify a Draft Order is created as a result.

Anchor to Test with a direct-to-consumer checkoutTest with a direct-to-consumer checkout
- Open your development store and log in as a direct-to-consumer customer.
- Build a cart with a total (including shipping and tax) over $5000.
- Since review requirements aren't applicable to D2C checkouts, the function doesn't add a review requirement.
- Verify that the checkout is not modified, and can be completed as normal.

Anchor to Next stepsNext steps
- Build a payment customization user interface with App Bridge.
- Learn how to use variables in your input query.
- Explore more payment customization options in the API reference.