Variables
For some Paywall strings you may want to set values based on the package that's being displayed instead of hardcoding a single value, such as when quoting a price, or describing the duration of an Introductory Offer.
To make this easier and ensure accuracy, we recommend using Variables for these values that are package-specific.
For example, to describe a trial that offers "1 week free", you should use the {{ product.offer_period_with_unit }} variable to insert 1 week to ensure the string is accurate for any product you use, even if you make changes to the product or its introductory offer in the future.
Product variables
Product variables are available for any package on your paywall. Use the {{ variable_name }} syntax to insert them into any text field. They are organized into the following categories:
All product variables return localized values based on the customer's device language and region. Prices are formatted with the appropriate currency symbol and separators (e.g., "$9.99" vs "9,99 €"), period text like "month" or "weekly" is translated to the device language, and dates follow the local format.
Pricing
| Variable | Description | Example |
|---|---|---|
| product.price | The localized price of the product. | $9.99 |
| product.price_per_period | Price with the billing period (e.g., "$9.99/month"). Lifetime products show price only. | $9.99/month |
| product.price_per_period_abbreviated | Price with abbreviated billing period (e.g., "$9.99/mo"). Lifetime products show price only. | $9.99/mo |
| product.price_per_day | Price normalized to a daily equivalent rate. Returns the full price for lifetime products. | $0.33 |
| product.price_per_week | Price normalized to a weekly equivalent rate. Returns the full price for lifetime products. | $2.50 |
| product.price_per_month | Price normalized to a monthly equivalent rate. Returns the full price for lifetime products. | $9.99 |
| product.price_per_year | Price normalized to an annual equivalent rate. Returns the full price for lifetime products. | $119.88 |
For lifetime (non-subscription) products, price normalization variables (price_per_day, price_per_week, etc.) return the full product price since there is no recurring period to normalize against. price_per_period and price_per_period_abbreviated return just the price without a period suffix.
Examples for all package types
| Variable | Weekly | Monthly | 2 Month | 3 Month | 6 Month | Annual | Lifetime |
|---|---|---|---|---|---|---|---|
| product.price | $2.99 | $9.99 | $17.99 | $24.99 | $39.99 | $69.99 | $119.99 |
| product.price_per_period | $2.99/week | $9.99/month | $17.99/2 months | $24.99/3 months | $39.99/6 months | $69.99/year | $119.99 |
| product.price_per_period_abbreviated | $2.99/wk | $9.99/mo | $17.99/2mo | $24.99/3mo | $39.99/6mo | $69.99/yr | $119.99 |
| product.price_per_day | $0.43 | $0.33 | $0.30 | $0.28 | $0.22 | $0.19 | $119.99 |
| product.price_per_week | $2.99 | $2.50 | $2.25 | $1.92 | $1.54 | $1.35 | $119.99 |
| product.price_per_month | $11.96 | $9.99 | $9.00 | $8.33 | $6.67 | $5.83 | $119.99 |
| product.price_per_year | $155.48 | $119.88 | $107.94 | $99.96 | $79.98 | $69.99 | $119.99 |
Subscription period
| Variable | Description | Example |
|---|---|---|
| product.period | Human-readable billing period (e.g., "month", "annual"). Returns "lifetime" for lifetime products. | month |
| product.period_abbreviated | Abbreviated billing period (e.g., "mo", "yr"). Returns "lifetime" for lifetime products. | mo |
| product.periodly | Adverb form of the billing period (e.g., "monthly", "annually"). Returns "lifetime" for lifetime products. | monthly |
| product.period_in_days | Billing period length in days. Returns an empty value for lifetime products. | 30 |
| product.period_in_weeks | Billing period length in weeks (rounded down). Returns an empty value for lifetime products. | 4 |
| product.period_in_months | Billing period length in months. Returns 0 for periods shorter than a month. Empty for lifetime. | 1 |
| product.period_in_years | Billing period length in years. Returns 0 for sub-annual periods. Empty for lifetime. | 0 |
| product.period_with_unit | Period with its unit spelled out (e.g., "1 month", "3 months"). Returns "lifetime" for lifetime products. | 1 month |
For lifetime products, numeric period variables (period_in_days, period_in_weeks, etc.) return an empty value since there is no recurring period. Text-based period variables (period, period_abbreviated, periodly, period_with_unit) return "lifetime".
Examples for all package types
| Variable | Weekly | Monthly | 2 Month | 3 Month | 6 Month | Annual | Lifetime |
|---|---|---|---|---|---|---|---|
| product.period | week | month | 2 months | 3 months | 6 months | annual | lifetime |
| product.period_abbreviated | wk | mo | 2mo | 3mo | 6mo | yr | lifetime |
| product.periodly | weekly | monthly | 2 months | 3 months | 6 months | annually | lifetime |
| product.period_in_days | 7 | 30 | 60 | 90 | 180 | 365 | N/A |
| product.period_in_weeks | 1 | 4 | 8 | 13 | 13 | 52 | N/A |
| product.period_in_months | 0 | 1 | 2 | 3 | 6 | 12 | N/A |
| product.period_in_years | 0 | 0 | 0 | 0 | 0 | 1 | N/A |
| product.period_with_unit | 1 week | 1 month | 2 months | 3 months | 6 months | 1 year | lifetime |
Currency
| Variable | Description | Example |
|---|---|---|
| product.currency_code | The ISO 4217 currency code for the product's price. | USD |
| product.currency_symbol | The currency symbol for the product's price. | $ |
Offer
These variables reference the active offer on a product. This includes introductory offers (free trials, pay-as-you-go, and pay-up-front) and promotional offers (App Store only). When a promotional offer is configured on a package and the user is eligible, it takes priority over an introductory offer for offer_* variables, and those variables will show the promotional offer's values instead of the introductory offer's.
These variables are typically used in the Text field for an introductory offer property on text components so they are only shown to eligible customers. See Supporting offers for more details on configuring offer eligibility.
If a product has no active offer (no introductory offer, no promotional offer, or the customer is not eligible), offer_price and offer_price_per_* variables fall back to the regular product price (and its normalized equivalents). All other offer variables (offer_period*, offer_end_date) return an empty value. Because of this fallback, we recommend using the Text field for an introductory offer on text components when referencing offer variables, so offer-specific messaging is only shown to eligible customers.
When a product has a free trial, offer_price returns the localized word "free" (not "$0.00"). This is automatically localized to the customer's device language.
If the intro offer period is shorter than the requested normalization unit, that variable returns empty. For example, offer_price_per_month returns empty if the intro offer is only 1 week long, and offer_price_per_year returns empty if the intro offer is only 3 months, since normalizing a shorter offer to a longer period would be misleading.
| Variable | Description | Example |
|---|---|---|
| product.offer_price | The localized offer price. Returns "free" for free trials. Falls back to regular price if no offer. | $1.99 |
| product.offer_price_per_day | Offer price normalized to a daily rate. Falls back to regular price if no offer. | $0.07 |
| product.offer_price_per_week | Offer price normalized to a weekly rate. Falls back to regular price if no offer, or empty if the offer period is shorter than a week. | $0.50 |
| product.offer_price_per_month | Offer price normalized to a monthly rate. Falls back to regular price if no offer, or empty if the offer period is shorter than a month. | $1.99 |
| product.offer_price_per_year | Offer price normalized to an annual rate. Falls back to regular price if no offer, or empty if the offer period is shorter than a year. | $23.88 |
| product.offer_period | Human-readable intro offer period (e.g., "week", "month"). Empty if no intro offer. | week |
| product.offer_period_abbreviated | Abbreviated intro offer period (e.g., "wk", "mo"). Empty if no intro offer. | wk |
| product.offer_period_in_days | Intro offer period length in days. Empty if no intro offer. | 7 |
| product.offer_period_in_weeks | Intro offer period length in weeks. Empty if no intro offer. | 1 |
| product.offer_period_in_months | Intro offer period length in months. Empty if no intro offer. | 0 |
| product.offer_period_in_years | Intro offer period length in years. Empty if no intro offer. | 0 |
| product.offer_period_with_unit | Intro offer period with unit spelled out (e.g., "1 week"). Empty if no intro offer. | 1 week |
| product.offer_end_date | The localized date when the intro offer ends. Empty if no intro offer. | December 31, 2024 |
Examples for all package types
| Variable | Weekly | Monthly | 2 Month | 3 Month | 6 Month | Annual | Lifetime |
|---|---|---|---|---|---|---|---|
| product.offer_price | $1.99 | $1.99 | $1.99 | $1.99 | $1.99 | $1.99 | N/A |
| product.offer_price_per_day | $0.07 | $0.07 | $0.07 | $0.07 | $0.07 | $0.07 | N/A |
| product.offer_price_per_week | $0.50 | $0.50 | $0.50 | $0.50 | $0.50 | $0.50 | N/A |
| product.offer_price_per_month | $1.99 | $1.99 | $1.99 | $1.99 | $1.99 | $1.99 | N/A |
| product.offer_price_per_year | $23.88 | $23.88 | $23.88 | $23.88 | $23.88 | $23.88 | N/A |
| product.offer_period | week | week | week | week | week | week | N/A |
| product.offer_period_abbreviated | wk | wk | wk | wk | wk | wk | N/A |
| product.offer_period_in_days | 7 | 7 | 7 | 7 | 7 | 7 | N/A |
| product.offer_period_in_weeks | 1 | 1 | 1 | 1 | 1 | 1 | N/A |
| product.offer_period_in_months | 0 | 0 | 0 | 0 | 0 | 0 | N/A |
| product.offer_period_in_years | 0 | 0 | 0 | 0 | 0 | 0 | N/A |
| product.offer_period_with_unit | 1 week | 1 week | 1 week | 1 week | 1 week | 1 week | N/A |
| product.offer_end_date | December 31, 2024 | December 31, 2024 | December 31, 2024 | December 31, 2024 | December 31, 2024 | December 31, 2024 | N/A |
Secondary offer
These variables reference the second phase of a multi-phase introductory offer, which is available on the Play Store when a product has both a free trial and a discounted intro price. Empty if no secondary offer exists.
| Variable | Description | Example |
|---|---|---|
| product.secondary_offer_price | The price of the second offer phase. Empty if no secondary offer. | $2.99 |
| product.secondary_offer_period | Human-readable period of the secondary offer. Empty if no secondary offer. | week |
| product.secondary_offer_period_abbreviated | Abbreviated period of the secondary offer. Empty if no secondary offer. | wk |
Examples for all package types
| Variable | Weekly | Monthly | 2 Month | 3 Month | 6 Month | Annual | Lifetime |
|---|---|---|---|---|---|---|---|
| product.secondary_offer_price | $2.99 | $2.99 | $2.99 | $2.99 | $2.99 | $2.99 | N/A |
| product.secondary_offer_period | week | week | week | week | week | week | N/A |
| product.secondary_offer_period_abbreviated | wk | wk | wk | wk | wk | wk | N/A |
Other
| Variable | Description | Example |
|---|---|---|
| product.relative_discount | Discount percentage compared to the most expensive package per period on the paywall. Empty for the most expensive package itself (it is the baseline). | 19% |
| product.store_product_name | The product display name as configured in App Store Connect or Google Play Console. | Pro Access |
relative_discount compares each package's normalized monthly price against the most expensive package per month on the paywall. For example, if you're displaying a monthly package at $10/month and a yearly package at $80/year ($6.67/month), the relative discount for the annual package would be 33%. The most expensive package per month returns an empty value (it is the baseline), so we recommend only using this variable within packages that are not the most expensive per period.
Examples for all package types
| Variable | Weekly | Monthly | 2 Month | 3 Month | 6 Month | Annual | Lifetime |
|---|---|---|---|---|---|---|---|
| product.relative_discount | 19% | 19% | 19% | 19% | 19% | 19% | 19% |
| product.store_product_name | Pro Access | Pro Access | Pro Access | Pro Access | Pro Access | Pro Access | Pro Access |
Custom variables
In addition to the product variables listed above, you can create Custom variables to insert dynamic content that isn't tied to a specific product. This is useful for displaying values like user-specific information, app state, or promotional messaging that changes based on your app's context.
Creating and using custom variables in the editor
To create a custom variable:
- In the paywall editor, select the Variables tab from the left-hand sidebar
- Click "Create variable"
- Set the name of the variable - this will be how you reference it in your paywall
- Give it a default value - this is what will be displayed in the preview and used as a fallback if no value is provided
The default value you set applies across your entire project, ensuring consistency wherever the variable is used. Once created, you can insert the custom variable into any text field using the same {{ custom.variable_name }} syntax.
Passing custom variable values from your app
When displaying a paywall in your app, you'll need to pass actual values for any custom variables you've created. This allows you to provide dynamic, context-specific content based on the user's session or app state.
For details on how to pass custom variable values when presenting a paywall, see Displaying Paywalls.
Countdown variables
When using a Countdown component on your paywall, you can use countdown-specific variables within any text component inside that countdown. These variables display the time remaining until the countdown's target date.
| Variable | Description | Example |
|---|---|---|
| count_days_with_zero | Days remaining with leading zero | 07 |
| count_days_without_zero | Days remaining without leading zero | 7 |
| count_hours_with_zero | Hours remaining with leading zero | 04 |
| count_hours_without_zero | Hours remaining without leading zero | 4 |
| count_minutes_with_zero | Minutes remaining with leading zero | 09 |
| count_minutes_without_zero | Minutes remaining without leading zero | 9 |
| count_seconds_with_zero | Seconds remaining with leading zero | 03 |
| count_seconds_without_zero | Seconds remaining without leading zero | 3 |
The values displayed by these variables depend on the Count From setting of your countdown component:
- Days: Shows total days with remainder hours (0-23), minutes (0-59), and seconds (0-59)
- Hours: Shows 0 days, total hours, remainder minutes (0-59), and seconds (0-59)
- Minutes: Shows 0 days, 0 hours, total minutes, and seconds (0-59)
Countdown variables are only available within text components that are inside a countdown component. They cannot be used elsewhere on your paywall.
Variable preview values
The paywall preview is generated using our example values for each package listed above, and therefore will differ from the actual values for the product's you choose to present on your paywall.
To see a more accurate preview, we recommend running your application on your physical device or in the simulator, as this will present details based on the actual information for the products you're displaying on that device.
Variable modifiers
We support a handful of modifiers that can be used to format the variable values:
uppercase: Converts the value to uppercase.lowercase: Converts the value to lowercase.capitalize: Capitalizes the first letter of each word in the value.
These modifiers can be used with the | operator after the variable name, for example:
{{ product.price_per_period }}will yield$2.99/week{{ product.price_per_period | uppercase }}will yield$2.99/WEEK{{ product.price_per_period | capitalize }}will yield$2.99/Week