Zum Inhalt springen

Set up the price metafield

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

A metafield is a box Shopify gives you to store your own information on a product, a variant or a customer. Custom Discount can read a price out of one, so the discount works from your data instead of from a number you type into the discount.

This page sets that up from nothing.

Most discounts do not.

What you wantMetafield needed?
20% off a collectionNo
£5 off each itemNo
Everything at a fixed £9.99Not with Custom Discount. Use a Product discount with Specific price.
Buy 6, pay £8.50 each; buy 12, pay £7.50 each — the same for every productNo, and not with Custom Discount either. Use a Price list discount with Fixed price per item.
Every product has its own contract price, and those prices already live in your ERP or a spreadsheetYes
A few hundred products, each with its own price breaksYes

The rule of thumb: if you would have to build one discount per product, a metafield turns it into one discount for all of them.

If you do not need one, stop here and go back to Custom Discount. Leave Read prices from a variant metafield switched off.

Step 1 — Create the definition in Shopify

Section titled “Step 1 — Create the definition in Shopify”

A definition tells Shopify the field exists and what shape it has. You do this once, not per product.

  1. In Shopify admin, open Settings → Metafields and metaobjects.

  2. Click Variants.

    Not Products. The discount reads the variant metafield, and these are two separate lists on the same screen.

  3. Click Add definition, top right.

  4. Type a Name.

    Volume pricing, or whatever you want to see on the product page.

    As you type, Shopify writes the field’s real address in small grey text underneath — here custom.volume_pricing. You do not type that yourself. Read it and remember it, because you will need both halves of it in step 3.

  5. Set Type to JSON.

    Click Select type, type JSON in the search box, and pick it. JSON is not in the recommended shortlist, so you have to search for it.

    Ignore the blue note about developer support. It is about showing the value in your theme, not about the discount.

    The Add variant metafield definition screen with Name set to Volume pricing, the generated address custom.volume_pricing shown underneath, and Type set to JSON
  6. Open Validation and paste a schema.

    Optional, and strongly worth doing. With it, Shopify refuses a broken value the moment anyone saves it, in the admin, in the bulk editor and through your ERP. Without it, a typo sits there silently and the discount just does not apply.

    The schema is yours and you can change it whenever you like. The discount never reads it — it reads the value. The schema is only Shopify’s spell-check at save time. Values already saved are left alone if you tighten it later; the new rules apply the next time someone edits that variant. Skip it entirely and everything still works, you just lose the safety net.

    {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "required": ["v"],
    "minProperties": 2,
    "maxProperties": 40,
    "properties": {
    "v": { "type": "integer", "enum": [1] },
    "unit": { "type": "string", "enum": ["minor", "major"] },
    "label": { "type": "string", "maxLength": 40 }
    },
    "patternProperties": {
    "^(qty|price|wholesale|floor|cap|min|max)[0-9]*$": {
    "type": "number", "minimum": 0, "maximum": 100000000
    }
    },
    "additionalProperties": { "type": ["number", "string", "boolean"] }
    }

    Paste it into the JSON Schema box and click Format JSON underneath. If it reformats neatly, the schema is valid.

    The Validation section of the definition screen, expanded, with the JSON schema pasted into the JSON Schema box and formatted
  7. Save.

Open any product. Scroll to the bottom. You will see two cards that look almost identical: Product metafields and Variant metafields.

The Shopify product page showing a Product metafields card with an empty Volume pricing field above a Variant metafields card whose Volume pricing field holds a JSON value

A value looks like this:

{ "v": 1, "qty6": 850, "qty12": 750 }

That reads: this variant costs 8.50 each when six are bought, and 7.50 each when twelve are. See what you may put in it below for every rule.

On the Custom Discount page, turn on Read prices from a variant metafield. Two boxes appear.

The Read prices from a variant metafield card, switched on, with Namespace set to custom and Key set to volume_pricing, help text explaining the JSON shape, and the Check a product button

Here is the part that catches people out. Shopify showed you one address with a dot in it. The discount asks for it as two boxes, without the dot.

WhereWhat you see or type
Shopify, under the definition Namecustom.volume_pricing — one line, with a dot, written for you
The discount, Namespace boxcustom
The discount, Key boxvolume_pricing

Never type the dot on the discount page, and never put the whole custom.volume_pricing into the Namespace box. Both boxes must match the definition exactly or no variant is found.

This address applies to the whole discount. One metafield per discount, read from every variant in the cart.

Then set a product offer’s Discount value to Price from product data and type the field name — qty in the example above, with Tiered by line quantity switched on.

Use Check a product on the same card to confirm it before you save. It reads a real variant and shows the price at each quantity, or the reason there is none.

This is the part that confuses people, so it is worth thirty seconds.

Think of a variant’s metafield as one row in your spreadsheet.

{ "v": 1, "qty6": 850, "floor": 700, "pack": 12, "season": "ss26" }

The discount has three slots, and you write a field name into each one. The metafield does not know or care which slot its names end up in.

SlotQuestion it answersWhere you set itExample
1Which items are in this deal?A condition in a cart grouppack, season
2What is the price?The offer’s Field boxqty
3What is the limit?The offer’s Floor field or Cap fieldfloor

It runs first and answers one question: is this item even in the deal? Nothing is discounted by this number, it only selects.

Cart: Mug A (has "pack": 12) Bowl B (has no "pack")
Cart group "Case packs" = Price data number, pack is greater than or equal to 6
Mug A passes → the offer applies to it
Bowl B fails → untouched, full price

It works like a collection, except you never maintain a list. Put "pack": 12 on a new SKU and it joins the deal by itself.

Use Price data number for a number and Price data field for text.

The only slot that produces money. It reads one number and turns it into a fixed price, an amount off, or a percentage, depending on What the number means on the offer. With Tiered by line quantity on it reads a family of names instead of one — see below.

There are two of them and they push in opposite directions.

SettingWhat it limitsPlain words
Floor fieldThe price, from belowNever sell below this
Cap fieldThe discount, from aboveNever take more than this off one unit

Floor, with "qty12": 600, "floor": 700:

the offer wants to charge 6.00
the floor says 7.00
────
sells at 7.00 the price hit the wall

Cap, with "off": 500, "cap": 200:

the offer wants to take off 5.00
the cap says at most 2.00
────
takes off 2.00 the discount hit the ceiling

Both are money and both follow the unit setting, the same as any other amount.

The value is a flat JSON object. Names on the left, values on the right, nothing nested.

{ "v": 1, "unit": "major", "qty6": 8.50, "qty12": 7.50, "floor": 7, "pack": 12, "season": "ss26" }
NameRequiredWhat it does
vYesThe format version. Must be 1. If it is missing or anything else, the whole metafield is ignored for that variant.
unitNoEither minor or major. Says how to read the numbers. Anything else and the whole metafield is ignored.

Every other name is yours. There is no fixed list, and qty6 is a convention in these examples, not a requirement. wholesale, trade_price, band_a all work.

What you writeHow it is readUsed for
A number, e.g. "qty6": 850An amount, or a value to comparePrices, amounts off, percentages, floors, caps, and Price data number conditions
Text, e.g. "season": "ss26"Text, never moneyPrice data field conditions, to select items
true, false, a list, a nested objectSkippedNothing. The rest of the metafield still works.

Rules for the names themselves:

  • Start with a letter or _, then letters, digits, _ or -. Up to 64 characters.
  • Names are case-sensitive. Qty6 and qty6 are different fields.

Numbers: whole minor units, or plain prices

Section titled “Numbers: whole minor units, or plain prices”

By default a number is a whole minor unit of your store currency. 850 means 8.50, 249 means 2.49. This is what most ERP exports already produce.

Add "unit": "major" and the same numbers are read as prices you would say out loud:

{ "v": 1, "unit": "major", "qty6": 8.50, "qty12": 7.50 }
  • The setting applies to the whole metafield, not one field. Pick one style per variant.
  • Under major, an amount with more decimals than your currency allows is ignored. 1.999 in a two-decimal currency, 15.5 in yen. It is never rounded into money.
  • A percentage ignores this setting entirely. 10 is 10% either way, and 12.5 is 12.5%.

Turn on Tiered by line quantity and give the offer a base name, say qty. The app then looks for that name with a number stuck on the end.

{ "v": 1, "qty1": 1000, "qty6": 850, "qty12": 750 }
Quantity in the lineTier usedEach item costs
1 to 5qty110.00
6 to 11qty68.50
12 or moreqty127.50

Three things worth knowing:

  • Tiers are per line. Six of a variant in one cart line reaches tier 6. Three plus three in two separate lines does not.
  • With tiers on, the bare name is not read. With Tiered by line quantity on and the field set to qty, a plain "qty": 800 is ignored. Add "qty1": 800 if you want a price below the first tier.
  • A base name must not end in a digit. price_1 with tiers on would read price_12 as tier 2. The app refuses that combination when you save.

Shopify’s bulk editor shows metafields as columns, so you can paste a value down a whole list.

Shopify's bulk editor listing fifty variants with a Volume pricing column, each row holding a JSON value such as v 1, pack 12, qty6 800

Open a product list, tick the variants, and click Bulk edit. Add the metafield as a column. For thousands of variants, write the same JSON through the Shopify API or your ERP integration. The value is just text, so anything that can set a metafield can set this.

  1. Is the value under Variant metafields? Product metafields are never read.
  2. Is "v": 1 there? Without it the whole metafield is skipped.
  3. Do the Namespace and Key boxes match the definition exactly? No dot, no typo, right case.
  4. Are the units right? 8.5 without "unit": "major" means eight and a half minor units, not 8.50, and is refused because it is not a whole number.
  5. Does the field name in the offer exist on that variant? Use Check a product. It names the reason.

A missing, zero, negative or unreadable number always means no discount on that item, never a guessed one. A discount that cannot be worked out exactly does not run.