Shopify Function - jerry-ey/shopify-theme-boilerplate GitHub Wiki

Tutorial: Building Shopify Functions with Rust

Shopify Functions allow developers to write custom logic that integrates directly into Shopify's backend workflows. This tutorial demonstrates how to create a Shopify Function using Rust.


Prerequisites

  1. Rust Installed:

    • Install Rust from rust-lang.org.
    • Ensure the cargo tool is available by running cargo --version.
  2. Shopify CLI:

  3. GraphQL Knowledge:

    • Familiarity with GraphQL queries and schemas is beneficial.

Setting Up Your Project

  1. Initialize a New Project:

    cargo new shopify-function-example
    cd shopify-function-example
    
  2. Add Dependencies: Update Cargo.toml to include Shopify-related dependencies.

    [dependencies]
    shopify_function = "0.1"
    serde = { version = "1.0", features = ["derive"] }
    serde_json = "1.0"
    decimal = "0.20"
    
  3. Install Shopify CLI Extensions:

    shopify extension create --type=discount_function
    

    Follow the prompts to configure the new function.


Writing the Function Logic

  1. Define the Function: Create a new file src/main.rs with the following content:

    use shopify_function::prelude::*;
    use shopify_function::Result;
    
    #[shopify_function_target(query_path = "src/run.graphql", schema_path = "schema.graphql")]
    fn run(input: input::ResponseData) -> Result<output::FunctionRunResult> {
        let no_discount = output::FunctionRunResult {
            discounts: vec![],
            discount_application_strategy: output::DiscountApplicationStrategy::FIRST,
        };
    
        let targets = input.cart.lines
            .iter()
            .filter(|line| line.quantity >= 2)
            .map(|line| output::Target::CartLine(output::CartLineTarget {
                id: line.id.to_string(),
                quantity: None,
            }))
            .collect::<Vec<output::Target>>();
    
        if targets.is_empty() {
            eprintln!("No cart lines qualify for volume discount.");
            return Ok(no_discount);
        }
    
        Ok(output::FunctionRunResult {
            discounts: vec![output::Discount {
                message: None,
                targets,
                value: output::Value::Percentage(output::Percentage {
                    value: Decimal(10.0),
                }),
            }],
            discount_application_strategy: output::DiscountApplicationStrategy::FIRST,
        })
    }
    
  2. GraphQL Schema: Create a schema.graphql file to define the input/output structure for your function:

    type Query {
        cart: Cart!
    }
    
    type Cart {
        lines: [CartLine!]!
    }
    
    type CartLine {
        id: ID!
        quantity: Int!
    }
    
  3. GraphQL Query: Create a src/run.graphql file to fetch the necessary data:

    query {
        cart {
            lines {
                id
                quantity
            }
        }
    }
    

Understanding the Code

  1. Procedural Macro:

    #[shopify_function_target(query_path = "src/run.graphql", schema_path = "schema.graphql")]
    

    This macro:

    • Links your function to Shopify’s backend.
    • Ensures compliance with the provided GraphQL schema and query.
  2. Filtering Logic:

    let targets = input.cart.lines
        .iter()
        .filter(|line| line.quantity >= 2)
    

    Filters cart lines where the quantity is 2 or more.

  3. Applying Discounts:

    Ok(output::FunctionRunResult {
        discounts: vec![output::Discount {
            value: output::Value::Percentage(output::Percentage {
                value: Decimal(10.0),
            }),
        }],
    })
    

    Creates a 10% discount for eligible items.


Testing Your Function

  1. Build the Project:

    cargo build --release
    
  2. Run Tests: Use the Shopify CLI to test the function:

    shopify extension serve
    
  3. Simulate Inputs: Use the Shopify GraphQL API to simulate various cart scenarios and verify the output.


Deploying the Function

  1. Bundle the Function:

    cargo build --release
    

    Upload the target/release binary to Shopify.

  2. Use Shopify CLI:

    shopify extension push
    

    Deploy the function to your Shopify store.


Additional Resources


By following this guide, you’ve successfully built a Shopify Function in Rust that applies discounts based on cart line quantities. Feel free to extend this example to meet your specific business logic!