Skip to main content
dashboard.liquid tags are grouped by default vs optional usage.
  • Default components are already present in the shipped dashboard.liquid template.
  • Optional components can be added or used to replace parts of the default layout.
Common tags are documented on Common tags: {% legacy_navbar %}.

Default components

Pause and resume actions

The default dashboard.liquid template includes pause or resume action links when subscription pausing is enabled for the project and the current subscription state allows the action. Use the same conditions in custom templates:
The action pages use the existing Customer Portal pause and resume confirmation flows.

{% subscription_pause_resume_banner %}

Block-style pause or resume callout. The default dashboard.liquid template includes this tag near the top of the dashboard for paused subscriptions, and below the shipment/frequency controls for active subscriptions. It renders when subscription pausing is enabled for the project and the current subscription can be paused or resumed. Active subscriptions show pause copy and a pause button. Paused subscriptions show paused-state copy and a resume button.

{% subscription_reactivation_banner %}

Lets customers restart a cancelled subscription from Customer Portal v2. It appears only for cancelled subscriptions when Customer Portal Subscription Reactivation is enabled in New Features. The current default dashboard.liquid template already includes this component. If your project uses a customized dashboard template, add the tag where customers should see the reactivation form:
The component supports optional customer-facing text:
For subscriptions with a flexible billing cycle or one shipment frequency for all products, customers must select the next billing date before reactivating. Plan-based subscriptions can use today, except Shopify subscriptions. Order-based and Shopify subscriptions can use tomorrow at the earliest. Plan-based projects also explain that the charge is created during the night following the selected date. After a successful reactivation, Firmhouse restores the subscription and clears its cancellation date. If the subscription cannot be reactivated, the customer stays on the dashboard and sees the reason.

ReferralCandy banner

The default dashboard.liquid template includes a ReferralCandy banner when subscription.referral_candy.url is available for the current subscription. The default banner:
  • Links More info to the customer’s ReferralCandy invite page (subscription.referral_candy.url)
  • Copies the customer’s ReferralCandy invite link from subscription.referral_candy.url
  • Shows the configured advocate reward discount from subscription.referral_candy.advocate_reward_discount when Firmhouse can resolve a valid reward for the subscription
  • Falls back to a generic translated message when the reward discount is unavailable
If you replace the default dashboard layout, add your own ReferralCandy block if you still want customers to see their personal referral link. subscription.referral_candy.url is only available when Firmhouse can fetch an invite link from ReferralCandy for the subscription. If the ReferralCandy campaign is stopped, paused, or configured in a way that prevents invite links from being created, the value is blank and the default banner stays hidden.

{% prepaid_renewal %}

Prepaid renewal notice and call to action. The default dashboard.liquid template includes this tag. It renders a renewal block for prepaid subscriptions when the renewal date is coming up and the prepaid subscription was created from a regular subscription through a prepaid upgrade. Customers can open the renewal options page from this block. On that page, they can keep renewing prepaid, switch back to the original regular billing subscription, or update the renewal payment date without changing their renewal option.

{% simple_next_billing_date_with_confirm %}

Inline editable next billing date control.

{% simple_plan_switch_with_confirm %}

Inline plan switch select with confirmation modal.
Using label_format: "both" combines plan name and frequency:

{% manage_products %}

Primary CTA to manage existing products.

{% product_quantity_progress %}

Progress and status widget for plan-based product quantity rules. This component only renders when the active plan has a minimum and/or maximum product quantity configured.
The default dashboard.liquid already includes this tag, and you can move or add it elsewhere in the template.
Sample scenarios:

{% product_listing %}

Main list of active ordered products.

{% product_listing_filtered %}

Filtered list of active ordered products. Use this tag when you want to split the dashboard product list into separate groups. If you do not pass a filter parameter, it renders the same active ordered products as the regular listing. shipment_schedule groups products by shipment schedule:
  • "recurring" shows products that ship more than once.
  • "one_time_purchase" shows products where the effective interval is only_once.
The filter is optional and only applies when shipment_schedule is passed.
You can combine shipment_schedule with a metadata filter:
Set show_replacement_button: true when customers should be able to replace products from that list. Replacement flows only swap the selected product and keep the existing ordered product quantity. Use hide_replacement_price: true when the replacement catalog and confirmation page should not show replacement prices.

{% next_order_price_overview %}

Core upcoming-order summary card. When show_discount_code_entry is enabled, the component shows a discount code field below the order summary. Customers can enter an active Firmhouse discount code and apply it to their subscription. After a valid code is applied, the upcoming order totals refresh automatically.

Enable discount code entry

Turn on Discount Codes in Customer Portal v2 in New Features for the project. The default Customer Portal v2 dashboard currently renders this component with show_discount_code_entry: false. Remove that parameter or set it to true in your custom dashboard.liquid template if customers should be able to apply discount codes from the portal. Firmhouse only shows the discount code field when the subscription does not already have an active promotion that blocks manual discount codes. Accepted discount codes must meet these conditions:
  • The discount code is active and has not reached its usage limit.
  • The linked promotion is active and available for the customer’s country.
  • The subscription has no active manual discount, including a promotion that was applied by another discount code.
  • Any active automatic discount on the subscription allows combining with manual discounts. In the discount settings, enable Allow this automatic discount to be combined with manual discounts.
  • The code is not a referral discount code. Referral codes are intended for new customer signup and first-order discounts, not recurring orders for existing customers.
  • For Shopify subscription contracts, the promotion should have simple rules to be synced to Shopify as a subscription contract discount. Codes for more complex Firmhouse-only advanced promotion rules are not supported yet.
If a subscription has an active manual discount, or an active automatic discount that does not allow combining with manual discounts, the discount code field stays hidden. Submitted discount codes are rejected with the existing active-discount message in the same situations. When one promotion with a public description is active on the subscription, the discount row shows that public description. When multiple promotions are active, or the active promotion has no public description, the row keeps the generic discount label. To control the customer-facing discount text, go to Discounts, open the order or billing cycle discount, and fill in Public description. Use wording that makes sense to customers, such as “10% off your next 2 orders”.
To show the discount code entry:

{% minimum_order_amount_warning %}

Warning shown when the next order preview does not meet the project’s minimum order amount. The default dashboard.liquid template includes this tag before the product list. It renders a warning only when all of these conditions are true:
  • The project is a dynamic subscription project.
  • The subscription is active.
  • Firmhouse can calculate the next order preview.
  • The next order subtotal before shipping and discounts is below the configured minimum order amount for the subscription country.
When customers add, remove, or update products from Customer Portal v2, the warning refreshes automatically together with the order summary.
The component uses the minimum order amount configured in Settings > Subscription. If you use country-specific minimum order amounts, Firmhouse uses the amount for the subscription’s country.

{% add_product %}

Secondary CTA to browse catalog and add products.

Optional components

{% asset_purchase_offers %}

Shows every asset on the subscription that the customer is currently eligible to purchase. The component renders nothing when no purchase offers are available. This component has no parameters.

{% asset_purchase_offer %}

Renders one asset purchase offer from an asset ownership Liquid object. Prefer asset_purchase_offers when Firmhouse should find and render every eligible offer automatically.

{% non_paying_banner %}

Displays an account warning when the subscription is marked as non-paying. It renders nothing for subscriptions in good payment standing.

{% latest_orders %}

Recent orders list.

{% next_order_preview %}

Upcoming order preview card.

Advanced product_listing_filtered patterns

Filtered product list card (for segmented subscriptions).
When show_replacement_button is enabled, customers can replace products in that filtered list. Replacement keeps the current ordered product quantity. Set hide_replacement_price: true if replacement prices should stay hidden in the catalog and confirmation step.

Dynamic groups based on ordered product metadata

If your filter_value should adapt to subscriber-specific metadata (for example names like "Veronika" or "Michiel"), you can build the group list from subscription.ordered_products and then render product_listing_filtered in a loop.

How are dynamic values fetched?

You can do this directly in dashboard.liquid; no custom backend endpoint is required.
  • subscription.ordered_products is available in SSCv2 Liquid context.
  • Each ordered_product includes metadata.
  • Reading ordered_product.metadata.group gives the current subscription’s group value for that ordered product (or use ordered_product.metadata.person if your project still uses the legacy key).
  • Pass filter_by with the same metadata key (group or person) that produced the value.
  • Looping over ordered products lets you discover all group values present on the active subscription at render time.
So the template itself can fetch values for the current subscription and render sections dynamically. If you need a list of possible groups that are not yet present on the subscription (for example, a global project-wide list), that is not available from this template context alone and should be handled outside the template (for example by pre-populating metadata values via your own flows). In this pattern:
  • hardcoded sections stay explicit (Add-ons, Gifts, One-time extras)
  • dynamic sections include only metadata values currently present on the subscription
  • hardcoded values are excluded from the dynamic loop
  • exclusions and de-duplication are done case-insensitively (downcase)
If your project stores group values under a different metadata key, replace ordered_product.metadata.group (and optional ordered_product.metadata.person fallback) with your key and pass that same key to filter_by.

Shopify instalment progress from ordered products

If your Shopify subscription setup uses instalment billing, you can render progress directly from the ordered products in dashboard.liquid.
  • ordered_product.instalment_current_number returns the current instalment number for that subscription line.
  • ordered_product.instalment_total_count returns the total instalment count from the subscription’s active plan.
  • subscription.active_plan.instalments is also available when you want to render plan-level instalment details outside the ordered product loop.
Example:

{% next_shipment_date %}

Localized next shipment date text.

{% minimum_contract_duration %}

Commitment/contract duration block.

{% billing_and_shipping_breakdown %}

Billing interval breakdown text.