> For the complete documentation index, see [llms.txt](https://help.pixfizz.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.pixfizz.com/products-and-design/pricing-formula-guide.md).

# Pricing Formula Guide

## Pixfizz Pricing Formula Mega-Guide

*Complete reference for product, variant, and option pricing*

***

### Overview

Pixfizz pricing is powered by **Ruby expressions** evaluated at runtime on:

* Products
* Product attributes
* Variants / options
* Variant values
* Price variables

Pricing formulas can range from:

* Simple static pricing
* Page-based pricing
* Quantity-based pricing
* Tiered volume discounting
* Sheet-based production pricing
* Combined formulas (pages × quantity × tiers)
* Price variable–driven pricing systems

This guide documents **all supported pricing patterns**, using **real-world Pixfizz examples**.

***

### Where Pricing Lives in Pixfizz

Pricing formulas can be defined in:

* **Product Attributes** → `Price`
* **Variants** → Value price fields
* **Variant Values**
* **Price Variables**
* **Option pricing (add-ons / upgrades)**

All formulas are evaluated **per orderline**, unless explicitly using `units` logic.

***

### Core Variables You Can Use

#### Quantity & Units

| Variable   | Meaning                                                 |
| ---------- | ------------------------------------------------------- |
| `quantity` | Quantity for *this orderline only*                      |
| `units`    | Quantity aggregated across orderlines (legacy behavior) |

> ⚠️ Prefer `quantity` unless you **explicitly want cross-orderline pricing**

***

#### Page-Based Variables (Books / Multipage Products)

| Variable          | Meaning                      |
| ----------------- | ---------------------------- |
| `pages`           | Total pages in the project   |
| `extra_pages`     | Pages above template minimum |
| `uncounted_pages` | Pages excluded from pricing  |

***

#### Cut Print / Photo Print Variables

| Variable             | Meaning                                 |
| -------------------- | --------------------------------------- |
| `cut_print_quantity` | Quantity derived from per-photo UI      |
| `pages`              | Often reused as “prints” in sheet logic |

***

#### Price Variables (Admin → Price Variables)

Price variables are **custom-defined constants**, for example:

```ruby
hardcover_base_a4
hc_extrapages_silk
whitelabel
```

> ⚠️ `whitelabel` is **not a system variable** — it is a **custom price variable**

***

### Simple Static Pricing

#### Fixed Price

```ruby
19.99
```

Used when pricing never changes.

***

### Page-Based Pricing

#### Base Price + Per-Page Increment

**Example:**\
$19.99 base for 16 pages, +$0.50 every 2 pages

```ruby
19.99 + (pages - 16) / 2 * 0.50
```

***

#### Using `extra_pages`

```ruby
19.99 + extra_pages / 2 * 0.50
```

> Uses the template’s minimum page count automatically.

***

#### Accounting for Uncounted Pages

```ruby
19.99 + ((pages - uncounted_pages) - 16) / 2 * 0.50
```

***

### Quantity-Based Pricing (Per Orderline)

#### Simple Unit Price × Quantity

```ruby
0.85 * cut_print_quantity
```

***

#### Tiered Quantity Pricing (Per Orderline)

```ruby
{
  1..10    => 0.59,
  11..49   => 0.49,
  50..249  => 0.44,
  250..499 => 0.39,
  500..2000=> 0.35
}.find { |range, unit_price|
  range.include?(cut_print_quantity)
}.last * cut_print_quantity
```

***

### Volume Discounting (Unit Price Changes by Quantity)

#### Example: Postcards / Prints

```ruby
{
  1..1     => 8.00,
  2..5     => 6.50,
  6..10    => 6.00,
  11..20   => 5.75,
  21..30   => 5.60,
  31..50   => 4.80,
  51..1000 => 4.15
}.find { |range, unit_price|
  range.include?(quantity)
}.last
```

***

### Combining Page Pricing + Volume Discounts

#### Photobook with Volume Discounts

```ruby
{
  1..1   => (19.99 + (pages - 16) / 2 * 0.50),
  2..5   => (18.99 + (pages - 16) / 2 * 0.45),
  6..10  => (17.99 + (pages - 16) / 2 * 0.40),
  11..20 => (16.99 + (pages - 16) / 2 * 0.35),
  21..1000 => (15.99 + (pages - 16) / 2 * 0.30)
}.find { |range, unit_price|
  range.include?(quantity)
}.last
```

***

### Sheet-Based Production Pricing

#### Charging by Print Sheets (Not Individual Items)

**Example:**

* 12 postcards per sheet
* First sheet: $10
* Each additional sheet: $8

```ruby
10 + (((pages - 12.0) / 12.0).ceil) * 8
```

#### Why This Works

* `pages` = number of postcards
* `.ceil` ensures partial sheets are charged
* Reflects **actual production cost**

***

### Pack-Based Pricing (e.g. Greeting Cards)

#### Price per Pack (10 cards per pack)

```ruby
{
  1..10   => 2.29,
  11..20  => 2.25,
  21..30  => 2.19,
  31..1000=> 2.10
}.find { |range, unit_price|
  range.include?(units)
}.last
```

> Quantity dropdown must enforce multiples of 10.

***

### Incremental Unit Pricing

#### First Unit Expensive, Rest Cheaper

```ruby
(10 + (units - 1) * 3.0) / units
```

* First unit = $10
* Each additional unit = $3

***

### Flat Pricing up to a Threshold

#### Example: Layflat Books

```ruby
49 + ([0, pages - 50].max / 4) * 2.5
```

* $49 covers up to 50 pages
* Every additional 4 pages = $2.50

***

### Using Price Variables (Advanced, Recommended)

#### Example: Hardcover Book with Whitelabel Multiplier

```ruby
i = 4
b = hardcover_base_a4
p = hc_extrapages_silk
e = (([24.0, pages - uncounted_pages].max - 24.0) / i).ceil

{
  1..4     => (b + e * p) * 1,
  5..19    => (b + e * p) * 0.9,
  20..49   => (b + e * p) * 0.8,
  50..1000 => (b + e * p) * 0.7
}.find { |range, unit_price|
  range.include?(quantity)
}.last * whitelabel
```

***

### Variant / Option Upgrade Pricing

#### Example: Paper Upgrade

```ruby
p = [24, pages - uncounted_pages].max - 24
i = 2

{
  1..4     => (199.0 + p / i * 15.0),
  5..19    => (199.0 + p / i * 15.0) * 0.9,
  20..49   => (199.0 + p / i * 15.0) * 0.8,
  50..1000 => (199.0 + p / i * 15.0) * 0.7
}.find { |range, unit_price|
  range.include?(units)
}.last
```

***

### Best Practices

* ✅ Prefer **clarity over cleverness**
* ✅ Use **price variables** for maintainability
* ❌ Do not assume `units` unless needed
* ❌ Do not “optimize” Ruby at the expense of readability
* ✅ Copy known-working patterns

***

### Common Pitfalls

| Issue                       | Fix                                       |
| --------------------------- | ----------------------------------------- |
| Unexpected discounts        | Use `quantity` instead of `units`         |
| Page math breaks            | Always use decimals (`12.0`)              |
| Whitelabel confusion        | Remember it’s a **custom price variable** |
| Partial sheet undercharging | Use `.ceil`                               |
