1. Overview

The ParityDeals React UI SDK provides a complete React-based solution for integrating dynamic, customizable pricing tables and paywalls into web applications. It handles fetching offering data, displaying pricing plans with multiple billing periods, managing subscriptions, and processing checkouts with full localization support.


2. Installation

Install the SDK using npm or yarn:

npm install @paritydeals/react-ui
# or
yarn add @paritydeals/react-ui

3. Quick Start

Basic Setup

Note: You must import the CSS file for the components to be styled correctly.

import { ParityDealsProvider, PDPricingTable } from '@paritydeals/react-ui';
import '@paritydeals/react-ui/dist/pd-react-ui.css';

function App() {
  return (
    <ParityDealsProvider
      accessToken="YOUR_ACCESS_TOKEN"
      offeringId="YOUR_OFFERING_ID"
      customerId="OPTIONAL_CUSTOMER_ID"
    >
      <PDPricingTable />
    </ParityDealsProvider>
  );
}

With Custom Event Handling

import { ParityDealsProvider, PDPricingTable } from '@paritydeals/react-ui';
import '@paritydeals/react-ui/dist/pd-react-ui.css';

function App() {
  const handleCustomPriceClick = (details) => {
    console.log('Custom price plan clicked:', details);
    // Handle custom pricing logic
  };

  return (
    <ParityDealsProvider
      accessToken="YOUR_ACCESS_TOKEN"
      offeringId="YOUR_OFFERING_ID"
      customerId="OPTIONAL_CUSTOMER_ID"
    >
      <PDPricingTable
        onCustomPriceClick={handleCustomPriceClick}
        customStyles={{
          style: {
            cardBackgroundColor: '#ffffff',
            buttonBackgroundColor: '#007bff',
            titleColor: '#333333'
          }
        }}
      />
    </ParityDealsProvider>
  );
}

4. Core Components

4.1. ParityDealsProvider

The top-level provider component that initializes the SDK and manages the global state.

Required Props

PropTypeDescription
accessTokenstringYour ParityDeals client access token
offeringIdstringThe unique identifier for your offering

Optional Props

PropTypeDefaultDescription
customerIdstringundefinedCustomer identifier for personalized pricing
checkoutSuccessUrlstringwindow.location.hrefURL to redirect after successful checkout
apiConfigParityDealsAPIConfig{}Advanced API configuration options

API Configuration Options

interface ParityDealsAPIConfig {
  onError?: (error: Error) => void;
  maxRetries?: number; // Default: 3
  timeout?: number; // Default: 5000ms
  backoffBaseDelay?: number;
  offeringApiUrl?: string;
  subscriptionApiUrl?: string;
  checkoutApiUrl?: string;
}

4.2. PDPricingTable

The main pricing table component that displays all plans and handles user interactions.

Props

PropTypeDefaultDescription
customStylesPricingTableStyle{}Custom styling configuration
customActionButtonCustomActionButtonundefinedCustom button component
customCheckIconReact.ReactNodeundefinedCustom check icon
customUnCheckIconReact.ReactNodeundefinedCustom uncheck icon
customTooltipIconReact.ReactNodeundefinedCustom tooltip icon
onCustomPriceClick(details: PlanClickDetails) => voidundefinedCallback for custom price plans
renderActionButtonAfterfeatures | pricepriceRender the action button after the features or the price
insertElements.*InsertElements{}Insert custom elements anywhere in the pricing table
insertElements.beforePlanName(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements before the plan name
insertElements.afterPlanName(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements after the plan name
insertElements.beforePlanDescription(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements before the plan description
insertElements.afterPlanDescription(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements after the plan description
insertElements.beforePrice(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements before the price
insertElements.afterPrice(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements after the price
insertElements.beforeFeatures(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements before the features
insertElements.afterFeatures(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements after the features
insertElements.beforeActionButton(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements before the action button
insertElements.afterActionButton(plan: OfferingPlan, activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements after the action button
insertElements.beforeSwitch(activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements before the switch
insertElements.afterSwitch(activePeriod: ChargePeriodEnum) => JSX.ElementundefinedInsert custom elements after the switch

Example Usage

<PDPricingTable
  onCustomPriceClick={(details) => {
    console.log('Custom plan selected:', details.plan.displayName);
    // Handle custom pricing logic
  }}
  customStyles={{
    style: {
      cardBackgroundColor: '#f8f9fa',
      buttonBackgroundColor: '#28a745',
      buttonColor: '#ffffff',
      titleColor: '#212529'
    },
    typography: {
      titleFontSize: 24,
      titleFontWeight: '600'
    },
    layout: {
      gap: 20,
      minWidth: 280,
      maxWidth: 400
    }
  }}
  insertElements={{
    afterPrice: (plan) => {
        if(plan.shouldHighlight) {
            return <div>Most popular plan</div>;
        }
        return null;
    }
  }}
/>

4.3. PDPlan

Renders a list of pricing plans with billing period switching.

Props

PropTypeRequiredDescription
plansOfferingPlan[]YesArray of plans to display
pricingTablePricingTableYesPricing table configuration
billingPeriodsBillingPeriod[]YesAvailable billing periods
countryCodestringYesCountry code for localization
currencyCodestringYesCurrency code (e.g., “USD”)
currencySymbolstringYesCurrency symbol (e.g., ”$“)
currencyConversionRatenumberYesCurrency conversion rate
pricingLocalestringYesLocale for price formatting
onPlanClick(details: PlanClickDetails) => voidYesPlan selection callback
customStylesPricingTableStyleNoCustom styling
customActionButtonCustomActionButtonNoCustom button component
actionButtonLoadingPlanIdentifierstringNoLoading state for specific plan
noStylesbooleanNoDisable default styling

4.4. PDPlanItem

Displays a single pricing plan card.

Props

PropTypeRequiredDescription
planOfferingPlanYesPlan data to display
pricingTablePricingTableYesPricing table configuration
periodChargePeriodEnumYesCurrent billing period
countryCodestringYesCountry code
currencyCodestringYesCurrency code
currencySymbolstringYesCurrency symbol
currencyConversionRatenumberYesConversion rate
pricingLocalestringYesLocale for formatting
onPdPlanItemClick(details: PlanClickDetails) => voidYesClick handler
customActionButtonCustomActionButtonNoCustom button
actionButtonTextstringNoButton text
actionButtonLoadingbooleanNoLoading state
actionButtonDisabledbooleanNoDisabled state
isActivebooleanNoActive plan indicator
successTextstringNoSuccess message
noStylesbooleanNoDisable styling

4.5. PDPrice

Renders formatted price display with currency and period information.

Props

PropTypeRequiredDescription
pricenumberYesPrice amount
countryCodestringYesCountry code
currencyCodestringYesCurrency code
currencySymbolstringYesCurrency symbol
currencyConversionRatenumberYesConversion rate
pricingLocalestringYesLocale for formatting
periodChargePeriodEnumYesBilling period
showDecimalbooleanYesShow decimal places
showCurrencySymbolbooleanYesShow currency symbol
showCurrencyCodebooleanYesShow currency code
minimumFractionDigitsnumberYesMinimum decimal places
maximumFractionDigitsnumberYesMaximum decimal places

4.6. PDFeatures

Renders the features list for a plan.

Props

PropTypeRequiredDescription
featuresOfferingFeature[]YesArray of features
periodChargePeriodEnumYesCurrent billing period
customCheckIconReact.ReactNodeNoCustom check icon
customUnCheckIconReact.ReactNodeNoCustom uncheck icon
customTooltipIconReact.ReactNodeNoCustom tooltip icon
descriptionTooltipEnabledbooleanNoEnable tooltips
onUsageChange(featureId: string, quantity: number) => voidNoUsage change handler

5. Data Types

Core Types

// Billing periods
enum ChargePeriodEnum {
  ONE_TIME = 'ONE_TIME',
  MONTHLY = 'MONTHLY',
  YEARLY = 'YEARLY',
  WEEKLY = 'WEEKLY',
  DAILY = 'DAILY',
  THREE_MONTHS = 'THREE_MONTHS',
  SIX_MONTHS = 'SIX_MONTHS'
}

// Price types
enum PriceTypeEnum {
  FREE = 'FREE',
  PAID = 'PAID',
  CUSTOM = 'CUSTOM'
}

// Price models
enum PriceModelEnum {
  FLAT = 'FLAT',
  PACKAGE = 'PACKAGE',
  TIERED = 'TIERED',
  VOLUME = 'VOLUME'
}

// Plan structure
interface OfferingPlan {
  id: string;
  name: string;
  displayName: string;
  displayDescription: string;
  identifier: string;
  isArchived: boolean;
  features: OfferingFeature[];
  price: OfferingPlanPrice;
  shouldHighlight: boolean;
  enabled: boolean;
}

// Plan click details
interface PlanClickDetails {
  plan: OfferingPlan;
  chargePeriod: ChargePeriodEnum;
  usageMap: Record<string, number>;
}

// Pricing table style
interface PricingTableStyle {
  style: PricingTableColorConfig;
  typography: PricingTableTypographyConfig;
  layout: PricingTableLayoutConfig;
}

Color Configuration

interface PricingTableColorConfig {
  primaryColor: string;
  primaryHoverColor: string;
  onPrimaryColor: string;
  secondaryColor: string;
  cardBackgroundColor: string;
  billingSwitchBackgroundColor: string;
  billingSwitchColor: string;
  billingSwitchSelectedColor: string;
  titleColor: string;
  descriptionColor: string;
  priceColor: string;
  priceUnitColor: string;
  pricePeriodColor: string;
  featureColor: string;
  dividerColor: string;
  buttonBackgroundColor: string;
  buttonColor: string;
  buttonHoverBackgroundColor: string;
  advancedMode: boolean;
}

Typography Configuration

interface PricingTableTypographyConfig {
  titleFontSize: number;
  titleFontWeight: string;
  descriptionFontSize: number;
  descriptionFontWeight: string;
  priceFontSize: number;
  priceFontWeight: string;
  priceUnitFontSize: number;
  priceUnitFontWeight: string;
  featureFontSize: number;
  featureFontWeight: string;
  pricePeriodFontSize: number;
  pricePeriodFontWeight: string;
}

Layout Configuration

interface PricingTableLayoutConfig {
  minWidth: number;
  maxWidth: number;
  gap: number;
  align: 'start' | 'center' | 'end';
}

6. Styling and Customization

6.1. CSS Variables

The SDK uses CSS variables for styling. You can override these in your CSS:

:root {
  /* Card & Background */
  --pd-card-bg: #ffffff;
  --pd-card-border-width: 1px solid;
  --pd-card-border-color: 1px solid;

  /* Text Colors */
  --pd-title-color: #171923;
  --pd-description-color: #718096;
  --pd-feature-color: #171923;

  /* Price Colors */
  --pd-price-color: #171923;
  --pd-price-unit-color: #171923;
  --pd-price-period-color: #718096;

  /* Button Colors */
  --pd-button-bg: #1A202C;
  --pd-button-hover-bg: #1A202C;
  --pd-button-color: #F7FAFC;

  /* Billing Switch Colors */
  --pd-billing-switch-bg: #1A202C;
  --pd-billing-switch-color: #F7FAFC;
  --pd-billing-switch-selected-color: #F7FAFC;

  /* UI Elements */
  --pd-divider-color: #E2E8F0;
  --pd-tooltip-bg: #2D3748;
  --pd-tooltip-color: #ffffff;

  /* Typography - Title */
  --pd-title-size: 24px;
  --pd-title-weight: 600;

  /* Typography - Description */
  --pd-description-size: 16px;
  --pd-description-weight: 400;

  /* Typography - Price */
  --pd-price-size: 28px;
  --pd-price-weight: 700;
  --pd-price-unit-size: 32px;
  --pd-price-unit-weight: 700;
  --pd-price-period-size: 16px;
  --pd-price-period-weight: 400;

  /* Typography - Feature */
  --pd-feature-size: 14px;
  --pd-feature-weight: 400;

  /* Layout */
  --pd-min-width: 360px;
  --pd-max-width: 400px;
  --pd-gap: 24px;
  --pd-align: center;
}

6.2. Custom Styles Object

const customStyles: PricingTableStyle = {
  style: {
    cardBackgroundColor: '#ffffff',
    buttonBackgroundColor: '#28a745',
    buttonColor: '#ffffff',
    titleColor: '#212529',
    descriptionColor: '#6c757d',
    priceColor: '#000000',
    featureColor: '#495057'
  },
  typography: {
    titleFontSize: 24,
    titleFontWeight: '600',
    descriptionFontSize: 14,
    descriptionFontWeight: '400',
    priceFontSize: 32,
    priceFontWeight: '700'
  },
  layout: {
    gap: 24,
    minWidth: 300,
    maxWidth: 450,
    align: 'center'
  }
};

6.3. Custom Action Button

const CustomButton: CustomActionButton = ({ onClick, children, plan, disabled }) => (
  <button
    onClick={onClick}
    disabled={disabled}
    className="my-custom-button"
    style={{
      backgroundColor: plan.shouldHighlight ? '#ff6b35' : '#007bff',
      color: '#ffffff',
      padding: '12px 24px',
      border: 'none',
      borderRadius: '6px',
      cursor: disabled ? 'not-allowed' : 'pointer'
    }}
  >
    {children}
  </button>
);

<PDPricingTable customActionButton={CustomButton} />

6.4. noStyles Mode

For complete styling control, use the noStyles prop:

<PDPricingTable noStyles={true} />

7. Advanced Features

7.1. Usage-Based Pricing

The SDK supports metered billing and tiered pricing:

// Features with usage tracking
const features = [
  {
    identifier: 'api_calls',
    displayName: 'API Calls',
    priceModel: PriceModelEnum.VOLUME,
    charges: [
      {
        chargePeriod: ChargePeriodEnum.MONTHLY,
        tiers: [
          { flatAmount: 0, unitAmount: 0.01, upTo: 1000 },
          { flatAmount: 10, unitAmount: 0.008, upTo: 10000 },
          { flatAmount: 82, unitAmount: 0.005, upTo: null }
        ]
      }
    ]
  }
];

7.2. Custom Price Plans

Handle custom pricing plans with the onCustomPriceClick callback:

<PDPricingTable
  onCustomPriceClick={(details) => {
    // Open contact form or custom pricing modal
    openCustomPricingModal(details.plan);
  }}
/>

7.3. Subscription Management

The SDK automatically handles subscription updates:

  • New Subscriptions: Redirects to checkout
  • Plan Upgrades/Downgrades: Updates existing subscription
  • Free Plan Upgrades: Handles free trial to paid conversion

7.4. Error Handling

<ParityDealsProvider
  accessToken="YOUR_TOKEN"
  offeringId="YOUR_OFFERING"
  apiConfig={{
    onError: (error) => {
      console.error('ParityDeals Error:', error);
      // Show user-friendly error message
      showErrorMessage('Unable to load pricing. Please try again later.');
    },
    maxRetries: 3,
    timeout: 10000
  }}
>
  <PDPricingTable />
</ParityDealsProvider>

8. Complete Example

import React from 'react';
import {
  ParityDealsProvider,
  PDPricingTable,
  PricingTableStyle
} from '@paritydeals/react-ui';

const App: React.FC = () => {
  const customStyles: PricingTableStyle = {
    style: {
      cardBackgroundColor: '#ffffff',
      buttonBackgroundColor: '#007bff',
      buttonColor: '#ffffff',
      buttonHoverBackgroundColor: '#0056b3',
      titleColor: '#212529',
      descriptionColor: '#6c757d',
      priceColor: '#000000',
      featureColor: '#495057',
      dividerColor: '#dee2e6',
      billingSwitchBackgroundColor: '#f8f9fa',
      billingSwitchColor: '#6c757d',
      billingSwitchSelectedColor: '#007bff'
    },
    typography: {
      titleFontSize: 24,
      titleFontWeight: '600',
      descriptionFontSize: 14,
      descriptionFontWeight: '400',
      priceFontSize: 32,
      priceFontWeight: '700',
      priceUnitFontSize: 16,
      priceUnitFontWeight: '400',
      featureFontSize: 14,
      featureFontWeight: '400',
      pricePeriodFontSize: 14,
      pricePeriodFontWeight: '400'
    },
    layout: {
      gap: 24,
      minWidth: 300,
      maxWidth: 450,
      align: 'center'
    }
  };

  const handleCustomPriceClick = (details) => {
    console.log('Custom plan selected:', details.plan.displayName);
    // Open contact form or pricing calculator
    window.open('/contact', '_blank');
  };

  return (
    <div className="app">
      <header>
        <h1>Choose Your Plan</h1>
        <p>Select the perfect plan for your needs</p>
      </header>
      
      <ParityDealsProvider
        accessToken="your-access-token"
        offeringId="your-offering-id"
        customerId="optional-customer-id"
        checkoutSuccessUrl="https://yourapp.com/success"
        apiConfig={{
          onError: (error) => {
            console.error('Pricing Error:', error);
          },
          timeout: 10000
        }}
      >
        <PDPricingTable
          customStyles={customStyles}
          onCustomPriceClick={handleCustomPriceClick}
        />
      </ParityDealsProvider>
    </div>
  );
};

export default App;

9. API Endpoints

The SDK uses the following default API endpoints:

  • Offering API: https://api.paritydeals.com/api/v1/monetization/public-offering
  • Checkout API: https://api.paritydeals.com/api/v1/checkout/
  • Subscription API: https://api.paritydeals.com/api/v1/subscriptions

You can override these in the apiConfig:

<ParityDealsProvider
  apiConfig={{
    offeringApiUrl: 'https://your-api.com/offerings',
    checkoutApiUrl: 'https://your-api.com/checkout',
    subscriptionApiUrl: 'https://your-api.com/subscriptions'
  }}
>

10. Troubleshooting

Common Issues

  1. Loading State: Ensure your accessToken and offeringId are correct
  2. Styling Issues: Check CSS variable overrides and custom styles
  3. API Errors: Verify API endpoints and network connectivity
  4. TypeScript Errors: Ensure all required props are provided

Debug Mode

Enable console logging for debugging:

<ParityDealsProvider
  apiConfig={{
    onError: (error) => {
      console.log('ParityDeals Debug:', {
        error: error.message,
        offeringId: 'your-offering-id',
        timestamp: new Date().toISOString()
      });
    }
  }}
>

12. Support

For technical support and questions: