Academy

Price Tables: Tiers, Billing Periods, and Rules

Build a price table that makes tiers, currency, billing periods, inclusions, exclusions, and verification dates clear to buyers, search engines, and AI agents.

15 min read

A price table turns a commercial offer into structured, comparable facts. A buyer can see what each tier costs, when the charge recurs, and what changes at the next tier without reconstructing the deal from labels, footnotes, and checkout copy. A machine can associate each amount with the correct currency, billing period, plan, inclusions, exclusions, and verification date.

Northstar plans — prices verified 27 August 2026
PlanPriceIncludedNot included
StarterUSD 29 per month, billed monthly1 workspace; 3 users; email supportAPI access; audit log
GrowthUSD 79 per month, billed monthly5 workspaces; 15 users; API access; audit logSingle sign-on
EnterpriseCustom quote, billed annuallyUnlimited workspaces; single sign-on; priority supportImplementation services, quoted separately

The company and plans above are illustrative. The structure is the production model: the currency is written as an ISO 4217 code, the recurrence and billing basis are separate facts, limits use numbers, absences are explicit, and the caption carries the date on which the commercial facts were checked.

Why this element matters

Pricing creates decision pressure because a reader is simultaneously testing affordability, fit, and risk. If “$79/month” actually means a USD 948 annual charge, or if the necessary API is a paid add-on, the apparent price is not the decision price. Keeping qualifications beside the amount lets buyers compare tiers on the same dimensions and exposes surprises before checkout.

The recommended tier must not be the only complete tier. Visual emphasis can guide attention, but missing facts force the reader to assume that the highlighted option is better. Trust comes from symmetric disclosure: every tier names its amount or quote status, period, commitment, core limits, material inclusions, and exclusions.

Machine extractability is the ability of a crawler, assistant, feed, or publishing system to retain the relationship between a fact and its subject. A visual card that splits “79”, “per month”, “billed annually”, and “Growth” into unrelated containers leaves that relationship to inference. Semantic headers expose the stable statement: “Growth costs USD 79 per month equivalent and is charged as USD 948 annually.”

Price is unusually volatile because promotions, taxes, currencies, packaging, and regional rules change. The verification date is therefore part of the element, not decoration: it states when the claim was checked and creates a refresh trigger.

When to use it

Use a price table when two or more purchasable tiers, packages, subscriptions, service levels, or volume bands share commercial terms. A single product can also use it when variants change price, quantity, term, or included scope. It is especially useful when billing cadence differs from the normalized comparison amount, such as “USD 20 per month, charged USD 240 annually.”

Use it for bounded facts: plan name, currency, amount, billing period, minimum quantity, trial conditions, included units, overage rate, and exclusions. Explain who each plan suits or how usage is measured in nearby prose.

Several near misses need a different element:

  • If the block judges products on quality, speed, support, or another non-commercial criterion without presenting purchasable terms, use a comparison table instead.
  • If one promotion has an expiry, eligibility rule, coupon, and call to action, use an offer box . Do not create a fake second tier merely to obtain a pricing layout.
  • If only one stable price and one purchase unit need stating, use a labelled price line within the owning product or service component. A four-column table adds friction without improving retrieval.
  • If a quote requires dependent inputs such as seats, storage, and contract length, use a calculator with a price summary.
  • If every customer receives a negotiated quote, show the pricing basis and enquiry path in prose or a single custom tier. Invented “starting at” amounts are not transparency.
  • If the block lists product specifications without a buying action or commercial terms, it is a spec table, even when one row happens to contain a price.

The element writing rules take precedence: choose the element by its purpose, not by its heading, card styling, or number of columns. A block whose job is to expose tiered commercial terms remains a price table even if the theme renders it as cards.

Logo

Ready to Monitor Your AI Visibility?

Track how AI chatbots mention your brand across ChatGPT, Perplexity, and other platforms.

Where to place it

Place the primary price table after the page has named the product, audience, and value proposition, but before detailed objections, testimonials, and the final call to action. On a dedicated pricing page, it is normally the first substantial section after the introduction. On a product or service page, place it after the scope explanation and before purchasing details.

Put prerequisite pricing logic immediately above the table. If prices exclude tax, require an annual commitment, assume five seats, or apply only in one region, state that condition before or in the caption. Put longer usage and overage definitions directly after the table. Never footnote a fact that changes the apparent amount.

Keep the plan name, price, currency, cadence, scope, verification date, and source as one unit. Do not place it beside a countdown timer, testimonial carousel, unrelated data table, or conflicting promotion. Do not separate the amount from “billed annually,” place a CTA between a tier header and its exclusions, or repeat different prices lower on the page.

On mobile, preserve this order: plan name, price and billing basis, included items, excluded items, then action. A matrix may scroll inside a labelled region; cards should stack without separating exclusions from their plan.

Anatomy

The labelled capture identifies these parts:

  1. Caption: names the product, market, and pricing context so the table still makes sense when extracted.
  2. Tier name: uses the official plan or package name, not an improvised audience label.
  3. Price: shows a numeric amount or the explicit status “Free,” “Custom quote,” or “Contact sales.”
  4. Currency: uses an ISO code such as USD, EUR, or GBP when a currency amount is present; a symbol may appear in addition.
  5. Normalized period: supports comparison, such as per month or per 1,000 requests.
  6. Billing basis: states what is actually charged and when, such as “USD 948 billed annually.”
  7. Included items: names the decisive capabilities, quantities, and service levels supplied at that price.
  8. Excluded items: states what a reasonable buyer might expect but will not receive, including paid add-ons.
  9. Action: uses a specific accessible label such as “Start Growth trial” rather than repeating “Choose” on every tier.
  10. Verification date: records the exact date the amounts and packaging were checked against the approved source.
  11. Tax and fee note: states whether displayed prices include applicable tax and identifies material mandatory fees.
  12. Source: identifies the billing catalogue, approved rate card, or commercial owner.

“Free” means no monetary charge under the stated conditions, not a trial that later bills. “Custom quote” means no public fixed amount, not zero. “Not included” means absent; “Add-on” means sold separately and should name its price or quote route when known.

Design examples

Every variant preserves currency, period, billing basis, scope, verification date, and accessible relationships.

Standard tier cards: use for two to four plans with short feature sets. Each card is an independently labelled tier with equivalent fields aligned.

Feature matrix: use when three to five tiers share many limits. Plan names are column headers and criteria are row headers. Repeat price and billing near the action in a long table, and give icons text equivalents.

Usage bands: use at declared quantity thresholds. Ranges must be exhaustive and non-overlapping: “1–10,000,” then “10,001–50,000.” State whether pricing is graduated, volume-based, or a flat package because each produces a different invoice.

Hybrid fixed and custom: use when self-serve tiers sit beside a negotiated plan. The custom tier still needs its basis, minimum commitment, scope, and contact action. Never use “0” or a dash for an unknown amount.

Parameters

The contract separates parent settings from tier data because currency and verification normally apply to the collection, while price, billing, and scope belong to one tier. “Source” means where the renderer obtains the parameter, not where the commercial claim was researched.

Price-table interface parameters
NameTypeRequiredMin/maxDefaultSource
titlePlain stringNo3–10 wordsAbsentFirst heading in body
captionPlain stringYes5–20 wordsNoneAttribute
variantEnum: cards, matrix, usage, hybridNoOne valuecardsAttribute
currencyISO 4217 codeYes for monetary pricesExactly 3 lettersNoneAttribute
marketPlain string or region codeConditional1 valueGlobalAttribute
verifiedISO 8601 dateYes1 exact valueNoneAttribute
tax-notePlain stringYes for monetary prices3–20 wordsNoneAttribute
sourcePlain text with optional URLYes1–2 primary sourcesNoneBody after tiers
tiersOrdered item collectionYes2–5; 1 allowed for a purchase variantNoneBody
tier.namePlain stringYes1–5 wordsNoneItem heading
tier.priceDecimal or enum: free, customYes0 or greater, or 1 enumNoneItem attribute
tier.periodISO 8601 duration or unit labelConditional1 valueNoneItem attribute
tier.billingPlain stringYes unless free2–12 wordsNoneItem attribute
tier.includedList of plain stringsYes3–8 itemsNoneItem body
tier.excludedList of plain stringsYes when expected limits exist1–5 itemsNoneItem body
tier.ctaLabel and absolute or root-relative URLYes2–5 label words; 1 URLNoneItem body
tier.recommendedBooleanNo1 valuefalseItem attribute

For usage pricing, period may be a unit such as 1000-requests rather than a time duration. The visible label must still read naturally. A normalized monthly equivalent may be shown, but billing must state the amount actually charged, the commitment, and the invoice cadence.

Syntax and code examples

All three notations map to the same ordered tiers and commercial fields. The portable directive is the canonical authored form; Hugo and WordPress are adapters, not separate definitions.

Portable Markdown directive

:::price-table{caption="Northstar plans" variant=cards currency=USD market=US verified=2026-08-27 tax-note="Prices exclude applicable tax"}
## Plans for growing teams

::item{price=29 period=P1M billing="USD 29 billed monthly"}
### Starter

Included: 1 workspace; 3 users; email support.
Excluded: API access; audit log.
CTA: [Start Starter trial](https://example.com/signup/starter)
::

::item{price=79 period=P1M billing="USD 79 billed monthly" recommended=true}
### Growth

Included: 5 workspaces; 15 users; API access; audit log.
Excluded: Single sign-on.
CTA: [Start Growth trial](https://example.com/signup/growth)
::

Source: approved billing catalogue, revision 2026-08-27.
:::

The first parent heading maps to title. Each item heading maps to tier.name; item attributes carry compact typed values; labelled body lines map to inclusions, exclusions, and action. Period uses an ISO 8601 duration when it represents time: P1M means one month and P1Y means one year.

Hugo shortcode

The intended adapter uses named parameters only and preserves the same nested fields. This sample documents the mapping; it does not require an article author to create a new shortcode.

{{< price-table caption="Northstar plans" variant="cards" currency="USD" market="US" verified="2026-08-27" taxNote="Prices exclude applicable tax" >}}
  {{< price-tier name="Starter" price="29" period="P1M" billing="USD 29 billed monthly" ctaLabel="Start Starter trial" ctaUrl="https://example.com/signup/starter" >}}
  Included: 1 workspace; 3 users; email support.
  Excluded: API access; audit log.
  {{< /price-tier >}}
  {{< price-tier name="Growth" price="79" period="P1M" billing="USD 79 billed monthly" recommended="true" ctaLabel="Start Growth trial" ctaUrl="https://example.com/signup/growth" >}}
  Included: 5 workspaces; 15 users; API access; audit log.
  Excluded: Single sign-on.
  {{< /price-tier >}}
  Source: approved billing catalogue, revision 2026-08-27.
{{< /price-table >}}

The renderer must produce a <table> with associated headers for a matrix or usage variant. A card variant must use a labelled list or sections whose heading, price, inclusions, exclusions, and action share one accessible group. It must not flatten the data into anonymous columns.

WordPress block

<!-- wp:amicited/price-table {"caption":"Northstar plans","variant":"cards","currency":"USD","market":"US","verified":"2026-08-27","taxNote":"Prices exclude applicable tax"} -->
  <!-- wp:amicited/price-tier {"name":"Starter","price":"29","period":"P1M","billing":"USD 29 billed monthly","included":["1 workspace","3 users","Email support"],"excluded":["API access","Audit log"],"ctaLabel":"Start Starter trial","ctaUrl":"https://example.com/signup/starter"} /-->
  <!-- wp:amicited/price-tier {"name":"Growth","price":"79","period":"P1M","billing":"USD 79 billed monthly","included":["5 workspaces","15 users","API access","Audit log"],"excluded":["Single sign-on"],"ctaLabel":"Start Growth trial","ctaUrl":"https://example.com/signup/growth","recommended":true} /-->
  <p>Source: approved billing catalogue, revision 2026-08-27.</p>
<!-- /wp:amicited/price-table -->

The registered block should edit tier data as fields and render semantic HTML on the server. Authors must not rebuild the element with generic columns, a screenshot, or manually aligned paragraphs because those forms discard the shared contract.

Examples

Good: the charge and scope are explicit

Beacon analytics plans for the United States — verified 27 August 2026
PlanPrice and billingIncludedNot included
CoreUSD 40 per month; USD 480 billed annuallyUp to 5 users; 100,000 events per month; 30-day retentionOverage events; single sign-on
ScaleUSD 95 per month; USD 1,140 billed annuallyUp to 20 users; 500,000 events per month; 12-month retentionImplementation service, quoted separately

Tax: prices exclude applicable sales tax. Source: illustrative approved rate card.

This works because the normalized monthly amounts are paired with the actual annual charges, limits use numbers, and expected exclusions are named. A buyer can calculate the commitment without opening a tooltip. A machine can bind each amount and constraint to a plan through the row and column headers.

Bad: the attractive number has no contract

PlanPriceFeatures
Good$40/mo*✓ Analytics, ✓ Support
BestCall usEverything you need

*Terms apply.

This fails for several independent reasons. The currency is inferred from a symbol, /mo does not say whether the buyer is charged monthly or annually, and the asterisk hides the material term. Checkmarks have no text state, “Support” has no channel or service level, and “Everything you need” is not a verifiable inclusion. “Call us” neither identifies a custom quote nor explains the pricing basis. There are no exclusions, limits, tax note, source, market, or verification date. The labels “Good” and “Best” also substitute persuasion for official plan identity.

Schema markup and accessibility

A price table feeds structured data only for an eligible, real offer. An Offer may carry price, priceCurrency, url, availability, and a genuine valid-through date. Connect multiple real offers to the same product or service; use AggregateOffer only for a truthful low-to-high range or offer collection. A pricing-card layout alone does not justify schema.

Use a price specification only when it accurately expresses the contract. Keep annual charge, monthly equivalent, minimum quantity, and overage logic distinct in source data. Visible content and structured output must agree. Omit numeric price for “Custom quote”; use zero only for a genuinely free offer.

Schema repeats a visible claim; it does not prove freshness. Generate page and structured output from the same approved source and compare them during QA. Never mark a promotion as permanent, invent validThrough, or expose a different currency.

A matrix needs a caption, plan column headers, criterion row headers, and scope attributes. Wrap a wide table in a named, keyboard-focusable region and let that region scroll when reflow would destroy relationships.

Card layouts need equivalent grouping. Make each tier name a heading and keep its price, billing, lists, and CTA in one labelled section. Write “Included,” “Not included,” “Add-on,” and “Recommended” in text rather than relying on position, color, or icons. A billing toggle must be keyboard operable, announce state, retain focus, and update both displayed and charged amounts.

Writing rules

Price copy is short because buyers scan it under uncertainty, but brevity must not erase the contract. State the reason for each constraint before applying it:

  • Stable names prevent mismatched plans. Use the official tier name in one to five words. Do not rename “Business Plus” as “Best value” in the heading; recommendation is a separate label.
  • Explicit amounts prevent false comparisons. Write the ISO currency code and number together, such as “EUR 49.” If tax, mandatory fees, or regional restrictions change the payable amount, state them in the element.
  • Cadence determines commitment. Keep the normalized period to one clear unit and the billing basis to two to twelve words. “Per month, billed annually at EUR 588” is clear; “from EUR 49/mo*” is not.
  • Numbers make limits testable. Use three to eight decisive inclusions per tier and quantify users, projects, storage, requests, retention, or response time. Replace “generous limits” with the actual threshold.
  • Named exclusions prevent assumption gaps. Include one to five exclusions when a reasonable buyer could expect them. State “Single sign-on: not included” or “Implementation: paid add-on,” not a dash.
  • Parallel language improves scanning. Use the same noun and unit across tiers: “5 users,” “20 users,” “Unlimited users,” rather than “Small team,” “20 seats,” and “No cap.”
  • A recommendation needs a disclosed reason. Use at most one recommended tier and explain the factual fit, such as “For teams needing API access.” Do not use fake scarcity, pulsing badges, or an unexplained “Most popular” claim.
  • Volatility requires ownership. Show one exact verification date and one primary source. Do not write “Prices correct at publication” because publication may be months or years earlier.
  • Compact cells preserve retrieval. Keep each inclusion or exclusion to two to eight words where possible. Move qualifications longer than one sentence below the table and link them back with a precise label.

Never put testimonials, competitor claims, legal terms, coupons, countdowns, or unsupported savings inside tier data. Evidence, legal detail, and promotions belong in their own elements or adjacent prose. Calculate savings only from a verified baseline and total.

Post types that use it

The postTypes frontmatter field is the source of this relationship. Each listed post type uses the element for a specific decision, not merely because the page mentions money.

Post typeRequirementWhy the price table belongs
Pricing pageCore when two or more public tiers or bands existIt is the canonical view of amounts, billing, limits, inclusions, exclusions, and actions.
Product pageConditionalUse it for purchase variants or subscriptions whose commercial terms differ.
Service pageConditionalUse it for standardized packages; negotiated work should expose the pricing basis without invented tiers.
Category pageConditionalUse it when the category itself has plans or membership levels, not to replace individual product prices.
Buying guideConditionalUse it for verified package costs when price is a decision criterion and the figures share one date and market.
Competitor comparison pageConditional and source-sensitiveUse it only for public, like-for-like tiers with visible verification dates and fair billing normalization.
Feature pageRareUse it when the feature is sold in explicit add-on tiers; otherwise link to the canonical pricing page.
Integration pageConditionalUse it when the integration has its own fixed connection, usage, or support tiers.

QA checklist

  • Does the block’s purpose match a price table under the precedence rule?
  • Does every tier use its official name and identify a numeric price, Free, or Custom quote?
  • Is every monetary amount paired with an ISO currency code and applicable market?
  • Are the normalized period and the amount actually billed both explicit?
  • Are annual totals, minimum commitments, setup fees, overages, tax treatment, and paid add-ons visible when applicable?
  • Do inclusions and exclusions use parallel, quantified labels across tiers?
  • Are usage bands exhaustive, non-overlapping, and identified as graduated, volume, or flat-package pricing?
  • Is the verification date exact, visible, and tied to an approved source owner?
  • Do page content, checkout or billing data, and structured data show the same commercial facts?
  • Does semantic markup associate each price and feature with the correct tier?
  • Are table captions, headers, scopes, card labels, toggle states, and CTA labels accessible?
  • Can the element reflow or scroll within its own labelled region without page-level horizontal scrolling?
  • Is color or iconography supported by text rather than carrying Included, Excluded, or Recommended alone?
  • Is a custom quote omitted from numeric price schema rather than encoded as zero?
  • Are promotions, testimonials, legal copy, and long explanations outside the canonical tier data?
  • Has someone recalculated annual equivalents, savings claims, quantity boundaries, and overage examples?

A price table is publishable only when a buyer and a machine can reconstruct the same offer from it. If either must guess the currency, commitment, scope, or freshness, the element is incomplete.

← All Academy tutorials

Ready to put it into practice?

Free check · 7-day trial · no credit card