> For the complete documentation index, see [llms.txt](https://docs.datajet-app.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.datajet-app.com/functions/functions/families-and-variables.md).

# Families and Variables

Functions run in a sandbox with no API access — the only data your code sees is the `input` object, and its contents are fixed when the function is created by choosing a **family**. The family can't be changed later, so pick the one that covers everything your rule needs.

When creating a function, the modal shows the exact **Available input** for the selected family and category. In the editor, autocomplete knows the same shape — type `input.` to explore what's available.

## Families

| Family                     | Input data                                                                                                                              | Variables                                                                                                   |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| General                    | Broad cart snapshot: totals, buyer identity and customer (name, amount spent, number of orders), lines and products, purchasing company | —                                                                                                           |
| Product                    | Cart lines with product tags, collection membership, a product metafield, line attributes                                               | `hasProductTags`, `inAnyCollection`, `productMetafieldNamespace`, `productMetafieldKey`, `lineAttributeKey` |
| Customer                   | Customer identity, tags, a customer metafield, amount spent, order count                                                                | `hasCustomerTags`, `customerMetafieldNamespace`, `customerMetafieldKey`                                     |
| Address                    | Shipping address fields, product tags, a cart attribute                                                                                 | `hasProductTags`, `cartAttributeKey`                                                                        |
| Address + Customer         | Shipping address, customer identity and tags, the selected delivery option                                                              | `hasCustomerTags`                                                                                           |
| Address + Product          | Shipping address, product tags and SKUs                                                                                                 | `hasProductTags`                                                                                            |
| Billing address            | Billing address fields, product tags                                                                                                    | `hasProductTags`                                                                                            |
| Billing + Shipping address | Both billing and shipping address fields                                                                                                | —                                                                                                           |
| Cart                       | Full cost breakdown (subtotal, tax, duty, compare-at), cart and line attributes                                                         | `cartAttributeKey`, `lineAttributeKey`                                                                      |
| Selling plan               | Selling plan allocations on cart lines (subscriptions), product tags                                                                    | `hasProductTags`                                                                                            |
| Shipping                   | The selected delivery option (title, method type), product and customer tags, a cart attribute                                          | `hasProductTags`, `hasCustomerTags`, `cartAttributeKey`                                                     |
| Tags                       | Product and customer tags together, line attributes                                                                                     | `hasProductTags`, `hasCustomerTags`, `lineAttributeKey`                                                     |
| Time                       | Shop local time comparisons, product and customer tags                                                                                  | `hasProductTags`, `hasCustomerTags`, `dateTimeAfter`, `dateTimeBefore`, `timeAfter`, `timeBefore`           |

## Two kinds of variables

Functions have two variable systems, opened from the segmented buttons in the editor toolbar:

* **Function** and **Global** — *code variables*: values your code reads through the `vars` object, like `vars.MAX_ORDER_TOTAL`. Use them instead of hardcoding thresholds and settings.
* **Query** — *query variables*: values that parameterize the function's **data query** on Shopify's side, like which tags each product is checked against.

## Code variables

Code variables use the **same format as** [**script variables**](/misc/variables.md): keys are `type#NAME` (a bare name implies `short_text`), plus an optional `metadata` object that turns variables into merchant-friendly input fields.

```json
{
  "short_text#MAX_ORDER_TOTAL": "5000",
  "checkbox#BLOCK_PO_BOXES": true,
  "metadata": {
    "MAX_ORDER_TOTAL": { "subtype": "number", "helpText": "Orders above this total are blocked" }
  }
}
```

Your code reads the stripped names through `vars`:

```javascript
if (parseFloat(input.cart.cost.totalAmount.amount) > parseFloat(vars.MAX_ORDER_TOTAL)) {
  return ['Orders above ' + vars.MAX_ORDER_TOTAL + ' are not allowed'];
}
return [];
```

* **Function** variables belong to one function. **Global** variables are shared with scripts and with every function on the store; a function variable overrides a global with the same name.
* The `metadata` property never reaches your code — it only drives the input fields. All metadata options from [script variables](/misc/variables.md) are supported.
* Values keep their JSON types: a `checkbox` arrives as a boolean, `json` as an object. There is no `secrets` access inside functions — don't store credentials in variables (the sandbox has no network access to use them anyway).

### Editing configuration from the dashboard

On the main dashboard's **Functions** tab, clicking a function expands its **Function configuration** — the same metadata-driven form merchants use for script tasks. Anyone can adjust values (a threshold, a toggle) without opening the code; saving applies to the live function on the next checkout.

## Query variables

Checkout data is fetched by a query that runs **before** your code — so anything dynamic in that query has to be set up front. That's what query variables are for: they parameterize the function's data query on Shopify's side. For example, `hasProductTags` controls which tags each product is checked against, and the result arrives in your `input` already resolved.

Open the **Query** button in the editor and provide a JSON object with the family's keys:

```json
{
  "hasProductTags": ["limited", "preorder"],
  "inAnyCollection": ["gid://shopify/Collection/123456789"]
}
```

| Variable                                              | Type                           | What it does                                                             |
| ----------------------------------------------------- | ------------------------------ | ------------------------------------------------------------------------ |
| `hasProductTags`                                      | array of strings               | Each product in `input` gets `hasTags: [{ tag, hasTag }]` for these tags |
| `hasCustomerTags`                                     | array of strings               | The customer gets `hasTags: [{ tag, hasTag }]` for these tags            |
| `inAnyCollection`                                     | array of collection IDs        | Each product gets `inCollections: [{ collectionId, isMember }]`          |
| `productMetafieldNamespace` / `productMetafieldKey`   | string                         | Each product gets `metafield: { value }` for this namespace/key          |
| `customerMetafieldNamespace` / `customerMetafieldKey` | string                         | The customer gets `metafield: { value }`                                 |
| `cartAttributeKey`                                    | string                         | The cart gets `attribute: { value }` for this key                        |
| `lineAttributeKey`                                    | string                         | Each cart line gets `attribute: { value }` for this key                  |
| `dateTimeAfter` / `dateTimeBefore`                    | string `"YYYY-MM-DDTHH:MM:SS"` | `input.shop.localTime` gets a boolean comparison against shop local time |
| `timeAfter` / `timeBefore`                            | string `"HH:MM:SS"`            | Same, for time of day                                                    |

**Reading the resolved values in code:**

```javascript
// hasProductTags: ["limited"]
var product = input.cart.lines[0].merchandise.product;
var isLimited = product && (product.hasTags || []).some(function (t) { return t.hasTag; });

// cartAttributeKey: "gift_wrap"
var giftWrap = input.cart.attribute && input.cart.attribute.value;

// Time family, timeAfter: "22:00:00"
var isLate = input.shop.localTime.timeAfter;
```

### Notes

* Only the family's own query variables are accepted — unknown keys are rejected on save.
* List variables can have at most **100 items** (Shopify's input query limit).
* Collection IDs can be provided as plain numbers (`123456789`) — they are converted to full Shopify IDs automatically.
* Empty values are dropped, so you can leave template keys you don't use untouched.
* Families without variables (*General*, *Billing + Shipping address*) need no setup — their input is fixed.
* Changing variables affects the live function on the next checkout, just like saving code.
