Skip to content

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.

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”.

PropTypeDefaultDescription
plansPPPPricingPlan[](required)Array of plan configurations
billingPeriod'monthly' | 'annual''monthly'Initial billing period
annualDiscountnumber0Percentage discount for annual billing
ctaTextstring'Get Started'Default CTA button text
onPlanSelect(plan) => voidCallback when a plan’s CTA is clicked
showBillingTogglebooleantrue if annualDiscount > 0Whether to show the monthly/annual toggle
showCountryBannerbooleantrueShow the “Prices adjusted for [Country]” banner
classNamestringCSS class for the container
noStylesbooleanfalseRender without default styles
headerReactNodeCustom content above the plans
PropertyTypeDefaultDescription
namestring(required)Plan name (e.g., “Pro”)
pricenumber(required)Monthly price in base currency. Use 0 for free plans.
featuresstring[](required)List of included features
highlightedbooleanfalseVisually highlight this plan (recommended plan)
descriptionstringShort description below the plan name
ctaTextstringOverride the default CTA text for this plan
planIdstringIdentifier passed to onPlanSelect

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
}}

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
/>

When a PPP discount is active, a banner appears above the pricing table showing:

🇮🇳 Prices adjusted for India 30% off

Disable it with showCountryBanner={false}.

The component ships with clean, minimal default styles:

  • Responsive gridgrid-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

For full control over styling, use noStyles:

<PPPPricingTable
plans={plans}
noStyles
className="my-pricing"
/>

The unstyled version renders with data attributes for CSS targeting:

AttributeElement
data-gopaylocal-pricing-tableRoot container
data-gopaylocal-pricing-country-bannerCountry adjustment banner
data-gopaylocal-pricing-toggleBilling toggle container
data-gopaylocal-pricing-plansPlans grid
data-gopaylocal-pricing-planIndividual plan card
data-highlightedSet on the highlighted plan
data-gopaylocal-pricing-plan-namePlan name
data-gopaylocal-pricing-plan-descriptionPlan description
data-gopaylocal-pricing-plan-pricePrice container
data-gopaylocal-pricing-plan-amountPrice amount text
data-gopaylocal-pricing-plan-periodPrice period (“/mo”)
data-gopaylocal-pricing-plan-featuresFeature list
data-gopaylocal-pricing-plan-ctaCTA 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;
}
<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}`;
}
}}
/>