How to build a price table and share it across listings
Create a rate card, tier it so a week costs less per day than a day does, attach it to many listings, and know what changes when you edit it.
Open in TWICE Admin
Catalog → Price Tables
A price table is a rate card. One object holds the prices for a selling mode, and any number of listings can point at it — so re-pricing a category is one edit rather than forty.This guide builds a shared table and tiers it by duration. If you only need to price a single listing, price a listing does that from the listing’s own Pricing tab and is the shorter road.
Required permission:catalog:price_table. Linked listings are a separate gate — catalog:price_table_linked_listings — so a role can be able to edit prices without being able to see which listings they affect.
A shared table is a shared consequence. The reason to build one is that editing it re-prices every listing linked to it at once. That is the feature, and it is also the trap: the Linked listings tab is the only thing standing between a routine price edit and forty listings changing.Check that tab before you edit an existing table, not after.
Go to Catalog → Price Tables and click Create Table.There is no dialog. TWICE creates the table straight away, names it Unnamed, and opens it. The steps below are editing a table that already exists.
2
Name it, and decide whether it is dated
On the General tab, Details holds two fields.Name is how you will recognise it in the picker when you attach it to a listing. It is internal — customers never see it — so name it after what it prices (“Standard bike rates”), not after a listing.Validity is the date window. Leave it empty and the table is always in play. Set it and the table’s rows only become candidates inside that window.Leave Validity empty on this table.Only price tables without a validity period can be used as a listing’s default price table — a dated table cannot be attached as a listing’s default, and it does not override one. Dated tables are a separate job — they layer over a default rather than replacing it, and the troubleshooting below covers what that does and does not let you charge.
3
Turn on the selling modes you actually use
The Prices card — set the prices and purchase types for the table — holds three independent sections: Purchase price, Booking price and Subscription.One table can carry all three. Turn off the ones you do not sell; the rows stay but the editing surface stops offering them.
4
Choose fixed or rate-based booking prices
Booking prices come in two shapes, and the choice decides what the customer does on the storefront.
Fixed price for duration — fixed prices for specified periods — e.g. 1 day or 3 hours. The customer picks one of your rows. Add them with Add fixed duration price.
Rate-based — the customer picks any start and end, and the engine prices the span from your rows. Add them with Add rate-based price.
Most rate cards are rate-based, because that is what makes tiering do any work. A fixed-price table with a day row and a week row offers exactly two options; a rate-based one covers everything in between.
5
Set the duration tiers
This is the actual rate card. Add one row per tier, each with a Period (a number and a unit) and a Base price:
Period
Base price
1 day
€40
3 days
€100
1 week
€180
The tiering is what makes a week cheaper per day than a day is. You do not configure a discount — you price the longer block lower per unit, and the engine does the rest.How the engine chooses. For each part of the booking it prefers the row with the longest duration that still fits, breaks ties on the lowest price, and fills any remainder with shorter rows and the Additional price rule. So a 9-day rental off the table above resolves as a week plus the rows that best cover the remaining two days — not as nine day-rows.Add rows at the durations customers actually book. A gap between 1 day and 1 week means every mid-length rental is priced out of day-rows.
6
Decide how a partial period is charged
Each row carries a pricing model, and it is the setting most worth getting right.Starting at pricing — charge for every calendar period the booking touches: a 23:00 pickup and a 01:00 return counts as two days. With it off, prices are charged by booked duration — a day is 24 hours from pickup.The unit dropdown names it per row: Day (Elapsed) versus Day (Started).This is a revenue decision, not a display one — it is the difference between a ski hire and a plant hire. Price a listing works through the reasoning; the choice you make there applies here.Sub-hour rows are always charged by duration, whatever the table’s model.
7
Attach the table to listings
A table with no listings pointing at it prices nothing. Attaching happens from the listing, not from the table: open a listing’s Pricing tab and pick this table.The picker only offers shared tables with no validity period, which is the same constraint from step 2 seen from the other end.The table’s Linked listings tab — listings using this price table — then lists everything attached, with Unlink on each row. That tab is your blast radius.
The table appears in Catalog → Price Tables with its Name, its Validity, and a Linked listings count. That count going up is the confirmation that attaching worked.The check that proves the tiering works is a real quote. Open one of the linked listings on the storefront and price a duration that should land on a longer tier — a 7-day rental on the table above should come out at €180, not 7 × €40. If it comes out as the sum of day-rows, the week row is not being selected, and the troubleshooting below covers why.
Editing the table changed prices on listings I wasn't thinking about
Working as designed, and the reason shared tables exist. Every linked listing re-prices together.What to do: open Linked listings before editing. If one listing needs to move independently of the others, give it its own table rather than editing the shared one — the shared table is the wrong instrument for a one-listing change.
A long rental is priced as a stack of day-rows
Cause: no longer row covers it, or a longer row exists but is more expensive per booking than the composition of shorter ones. The engine takes the cheapest valid coverage, so an over-priced week row simply never gets selected.What to do: check the week row is enabled, and check its price against 7 × the day row. A week priced at or above seven days is not a tier — it is a row that will never win.
I set a higher holiday rate and customers still get the normal price
Cause: a dated table does not override the default — its rows compete in the same pool, and the cheaper row wins.What to do: a cheaper promotional row works with no further effort. A higher one does not, and needs the competing default row removed or date-restricted for that window so nothing cheaper covers it. The mechanism is set out in Price resolution.
I cannot attach my dated table to a listing
Working as designed. Only tables without a validity period can be a listing’s default, and the picker filters to those.What to do: keep an undated table as the baseline and let dated tables layer over it. A dated table is an overlay, never a substitute for having a default.
Part of a booking has no price
Cause: rows carry optional weekday, time of day and date restrictions, and a segment matching none of them falls through.What to do: give at least one row a fallback price so any uncovered segment has something to resolve against. Where several rows offer one, the cheapest applicable wins.
The same listing needs different prices per location or per channel
Not available. A table is scoped by validity period and nothing else. There is no per-location or per-channel price.What to do: two locations that must charge differently need separate listings with separate tables — which also means separate stock rules and separate publishing. Worth being sure the difference justifies that.
I want a rate for one customer segment
Not on a price table. There is no per-customer-tag pricing in the model.What to do: use a discount code restricted to the listings or collections in question. A staff-only code covers the contract-rate case.