Skip to main content

Core Concepts

Understanding the fundamental building blocks of Function Lab.

Overview

Function Lab configurations consist of rules that evaluate conditions and execute events. Optional facts enable complex data transformations.
Input Data → Facts → Conditions → Events → Output

Rules

A rule is the basic unit of logic in Function Lab.

Structure

{
  "rules": [
    {
      "facts": { /* optional data transformations */ },
      "conditions": { /* when to apply this rule */ },
      "events": [ /* what to do when conditions match */ ]
    }
  ]
}

Required Fields

  • conditions: Object defining when the rule applies
  • events: Array of actions to take when conditions are met

Optional Fields

  • facts: Named calculations for reuse in conditions and events
  • if-not-events: Alternative events when conditions don’t match

Conditions

Conditions determine when a rule should fire. They query the input data using dot notation and predicates.

Simple Condition

{
  "conditions": {
    "customer.tags": {
      "includes": "VIP"
    }
  }
}
Checks if customer tags array includes “VIP”.

Multiple Conditions (AND)

{
  "conditions": {
    "customer.tags": {
      "includes": "VIP"
    },
    "cart.totalAmount": {
      "gte": 100
    }
  }
}
Both conditions must be true (implicit AND).

OR Logic

{
  "conditions": {
    "or": [
      { "customer.tags": { "includes": "VIP" } },
      { "customer.tags": { "includes": "WHOLESALE" } }
    ]
  }
}

Available Predicates

PredicateDescriptionExample
equal, eq, isExact match"customer.email": { "is": "user@example.com" }
includes, containsArray contains value"customer.tags": { "includes": "VIP" }
gt, greaterGreater than"cart.totalAmount": { "gt": 100 }
gte, greaterEqGreater than or equal"cart.totalAmount": { "gte": 100 }
lt, lessLess than"cart.lineCount": { "lt": 5 }
lte, lessEqLess than or equal"cart.lineCount": { "lte": 10 }
existsField exists"customer.id": { "exists": true }
emptyArray/string is empty"customer.tags": { "empty": false }
See Predicates Reference for complete list.

Events

Events define what happens when conditions match. Event structure depends on the function type.

Product Discount Event

{
  "events": [
    {
      "discount": "product_discount",
      "params": {
        "discount_type": "percentage",
        "value": 15,
        "message": "15% Off Sale"
      }
    }
  ]
}

Multiple Events

A rule can have multiple events:
{
  "events": [
    {
      "discount": "product_discount",
      "params": {
        "handles": ["t-shirt"],
        "discount_type": "percentage",
        "value": 20,
        "message": "20% off T-Shirts"
      }
    },
    {
      "discount": "product_discount",
      "params": {
        "handles": ["jeans"],
        "discount_type": "percentage",
        "value": 15,
        "message": "15% off Jeans"
      }
    }
  ]
}

Facts

Facts are named calculations that transform input data for reuse in conditions and events.

Basic Fact

{
  "facts": {
    "total_quantity": "cart.lines[].quantity | sum(@)"
  },
  "conditions": {
    "$total_quantity": { "gte": 10 }
  }
}
The $ prefix references a fact in conditions.

Why Use Facts?

  • Reusability: Calculate once, use everywhere
  • Readability: Name complex expressions
  • Performance: Avoid redundant calculations
  • Power: Use JMESPath or custom filters for complex queries

Example: Collection Filtering

{
  "facts": {
    "sale_items": "cart.lines[?merchandise.product.collections[?handle=='sale']].id"
  },
  "conditions": {
    "$sale_items": { "empty": false }
  },
  "events": [
    {
      "discount": "product_discount",
      "params": {
        "selector": "$sale_items",
        "discount_type": "percentage",
        "value": 25,
        "message": "25% off Sale Items"
      }
    }
  ]
}
See Facts System for deep dive.

Input Data Structure

Function Lab receives cart and customer data from Shopify in a standardized format:
{
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/...",
        "quantity": 2,
        "merchandise": {
          "id": "gid://shopify/ProductVariant/...",
          "title": "Size M",
          "product": {
            "id": "gid://shopify/Product/...",
            "title": "Cool T-Shirt",
            "handle": "cool-t-shirt",
            "vendor": "Awesome Brand",
            "collections": [...]
          }
        }
      }
    ],
    "totalAmount": 100.00,
    "buyerIdentity": {
      "customer": {
        "id": "gid://shopify/Customer/...",
        "email": "customer@example.com",
        "tags": ["VIP", "WHOLESALE"]
      }
    }
  }
}
See Input Structure Reference for complete schema.

Path Notation

Access nested data using dot notation:
PathAccesses
customer.emailCustomer’s email address
customer.tagsArray of customer tags
cart.linesArray of cart line items
cart.lines[].merchandise.product.handleProduct handles for all lines

Array Access

Arrays are automatically traversed:
{
  "customer.tags": { "includes": "VIP" }
}
Checks if any tag equals “VIP” (automatic ANY semantics).

Execution Flow

  1. Input Received: Shopify sends cart/checkout data
  2. Facts Computed: Named calculations evaluated once
  3. Conditions Evaluated: Check if rule should fire
  4. Events Executed: Generate discounts/operations
  5. Output Returned: Results sent back to Shopify

Next Steps

I