Pricing Table Component
Drop-in PPP-aware pricing table that auto-adjusts prices for every visitor.
The PPPPricingTable is a drop-in pricing table component that automatically localizes prices with PPP discounts and currency conversion. No manual price calculation needed.
Quick Example
Section titled “Quick Example”import { GoPayLocalProvider, PPPPricingTable } from '@gopaylocal/react';
function PricingPage() { return ( <GoPayLocalProvider apiKey="gpl_pk_live_abc123"> <PPPPricingTable plans={[ { name: 'Free', price: 0, features: ['1 product', '10K API hits/mo', 'Try every feature'], }, { name: 'Pro', price: 19, features: [ '10 products', '500K API hits/mo', '3 team members', '90-day analytics', 'No branding', 'Webhooks', ], highlighted: true, description: 'Most popular', }, { name: 'Business', price: 49, features: [ '50 products', '5M API hits/mo', '10 team members', '365-day analytics + export', 'No branding', 'Custom parity groups', ], }, { name: 'Scale', price: 99, features: [ 'High-volume products', 'High-volume API hits', 'More team members', '365-day analytics + export', 'No branding', 'Priority support + onboarding', ], }, { name: 'Enterprise', price: 0, features: [ 'Custom products', 'Custom API hits', 'Unlimited team members', 'SSO/SAML', 'Audit logs', '99.99% SLA', 'Dedicated support + Slack', ], ctaText: 'Contact Sales', }, ]} annualDiscount={20} ctaText="Get Started" onPlanSelect={(plan) => { console.log('Selected:', plan.name, plan.finalPrice); // Redirect to checkout }} /> </GoPayLocalProvider> );}A visitor from India would see prices like “Free”, “₹999/mo”, and “₹2,499/mo” instead of “$0”, “$19/mo”, and “$49/mo”.
PPPPricingTableProps
Section titled “PPPPricingTableProps”| Prop | Type | Default | Description |
|---|---|---|---|
plans | PPPPricingPlan[] | (required) | Array of plan configurations |
billingPeriod | 'monthly' | 'annual' | 'monthly' | Initial billing period |
annualDiscount | number | 0 | Percentage discount for annual billing |
ctaText | string | 'Get Started' | Default CTA button text |
onPlanSelect | (plan) => void | — | Callback when a plan’s CTA is clicked |
showBillingToggle | boolean | true if annualDiscount > 0 | Whether to show the monthly/annual toggle |
showCountryBanner | boolean | true | Show the “Prices adjusted for [Country]” banner |
className | string | — | CSS class for the container |
noStyles | boolean | false | Render without default styles |
header | ReactNode | — | Custom content above the plans |
PPPPricingPlan
Section titled “PPPPricingPlan”| Property | Type | Default | Description |
|---|---|---|---|
name | string | (required) | Plan name (e.g., “Pro”) |
price | number | (required) | Monthly price in base currency. Use 0 for free plans. |
features | string[] | (required) | List of included features |
highlighted | boolean | false | Visually highlight this plan (recommended plan) |
description | string | — | Short description below the plan name |
ctaText | string | — | Override the default CTA text for this plan |
planId | string | — | Identifier passed to onPlanSelect |
onPlanSelect Callback
Section titled “onPlanSelect Callback”When a user clicks a plan’s CTA button, onPlanSelect is called with the plan data plus computed values:
onPlanSelect={(plan) => { console.log(plan.name); // "Pro" console.log(plan.price); // 9 (original) console.log(plan.finalPrice); // 499 (localized, discounted) console.log(plan.billingPeriod); // "monthly" | "annual" console.log(plan.planId); // Custom plan ID, if set}}Billing Toggle
Section titled “Billing Toggle”When annualDiscount is greater than 0, a monthly/annual toggle appears automatically. The annual price is calculated as:
annual price = monthly price × (1 - annualDiscount/100)Then PPP discount and FX conversion are applied on top.
<PPPPricingTable plans={plans} annualDiscount={20} // 20% off for annual billing/>The toggle shows “Monthly” and “Annual (-20%)” buttons. You can control the initial state with billingPeriod:
<PPPPricingTable plans={plans} annualDiscount={20} billingPeriod="annual" // Start with annual selected/>Country Banner
Section titled “Country Banner”When a PPP discount is active, a banner appears above the pricing table showing:
🇮🇳 Prices adjusted for India 30% offDisable it with showCountryBanner={false}.
Default Styles
Section titled “Default Styles”The component ships with clean, minimal default styles:
- Responsive grid —
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)) - Highlighted plan — Blue border with subtle shadow
- Feature checkmarks — Green check marks next to each feature
- Toggle — Pill-style toggle with active state
- Country banner — Green card with flag emoji
Unstyled Mode
Section titled “Unstyled Mode”For full control over styling, use noStyles:
<PPPPricingTable plans={plans} noStyles className="my-pricing"/>The unstyled version renders with data attributes for CSS targeting:
| Attribute | Element |
|---|---|
data-gopaylocal-pricing-table | Root container |
data-gopaylocal-pricing-country-banner | Country adjustment banner |
data-gopaylocal-pricing-toggle | Billing toggle container |
data-gopaylocal-pricing-plans | Plans grid |
data-gopaylocal-pricing-plan | Individual plan card |
data-highlighted | Set on the highlighted plan |
data-gopaylocal-pricing-plan-name | Plan name |
data-gopaylocal-pricing-plan-description | Plan description |
data-gopaylocal-pricing-plan-price | Price container |
data-gopaylocal-pricing-plan-amount | Price amount text |
data-gopaylocal-pricing-plan-period | Price period (“/mo”) |
data-gopaylocal-pricing-plan-features | Feature list |
data-gopaylocal-pricing-plan-cta | CTA button |
Example CSS:
[data-gopaylocal-pricing-plan] { border: 1px solid #e5e7eb; border-radius: 12px; padding: 32px 24px;}
[data-gopaylocal-pricing-plan][data-highlighted] { border-color: #e94560; box-shadow: 0 4px 14px rgba(233, 69, 96, 0.15);}
[data-gopaylocal-pricing-plan-cta] { background: #e94560; color: white; border: none; border-radius: 8px; padding: 12px 24px; font-weight: 600; cursor: pointer;}Full Example with Custom Header
Section titled “Full Example with Custom Header”<PPPPricingTable header={ <div style={{ textAlign: 'center', marginBottom: 32 }}> <h2>Simple, transparent pricing</h2> <p>All features included. Upgrade when you need scale.</p> </div> } plans={[ { name: 'Starter', price: 0, features: ['1 product', '10K requests', 'Community support'], ctaText: 'Start Free', }, { name: 'Pro', price: 19, features: ['10 products', '500K requests', 'Priority email support'], highlighted: true, description: 'Best for growing businesses', planId: 'pro_monthly', }, { name: 'Business', price: 49, features: ['50 products', '5M requests', 'Custom parity groups'], planId: 'business_monthly', }, { name: 'Enterprise', price: 0, features: ['Unlimited everything', 'SSO/SAML', '99.99% SLA', 'Dedicated support'], ctaText: 'Contact Sales', planId: 'enterprise', }, ]} annualDiscount={20} onPlanSelect={(plan) => { if (plan.planId === 'enterprise') { window.location.href = '/contact'; } else { window.location.href = `/checkout?plan=${plan.planId}`; } }}/>