Skip to main content
The @kelviq/react-promotions-ui SDK provides React components for displaying location-based promotional banners and dynamically discounted prices. It handles API communication, discount calculation, and currency formatting out of the box.
  • A React Context Provider (KQProvider) to fetch and share promotion data
  • A banner component (KQBanner) with template variables and full styling control
  • Price components for formatted display of discounted prices
  • Granular price components for building fully custom price layouts
This SDK is separate from the entitlements React SDK and the React UI SDK. Use this SDK when you need PPP / country-based discount banners and price display in a React app.

Installation

npm install @kelviq/react-promotions-ui
# or
yarn add @kelviq/react-promotions-ui
Requires react and react-dom as peer dependencies (v17, v18, or v19).

Quick start

Wrap your app with KQProvider and place KQBanner where you want the banner to appear.
import { KQProvider, KQBanner } from '@kelviq/react-promotions-ui';

function App() {
  return (
    <KQProvider
      promotionId="YOUR_PROMOTION_ID"
      accessToken="YOUR_ACCESS_TOKEN"
    >
      <KQBanner />
      {/* Your app components */}
    </KQProvider>
  );
}
Never expose your Server API Key in the browser. Use the Client API Key, which is safe for client-side code. You can find both keys under Settings → Developers in the Kelviq dashboard.

KQProvider

The provider initializes the SDK, fetches promotion data from the Kelviq API, and makes it available to all child components via React Context.

Props

PropTypeDefaultDescription
promotionIdstring''The promotion ID from the Kelviq dashboard
accessTokenstring''Client API Key (Settings → Developers)
kqIdentifierstring''Optional Kelviq identifier for the request
environment'production' | 'sandbox''production'Set to 'sandbox' to use the sandbox API
baseCurrencyCodestring'USD'ISO 4217 currency code used for formatting
baseCurrencySymbolstring'$'Currency symbol for display
configobject{}Advanced configuration (see below)

Advanced config

The optional config prop accepts:
FieldTypeDefaultDescription
apiUrlstringOverride the default API endpoint
onError(error: Error) => voidError callback for API failures
maxRetriesnumber3Maximum retry attempts for failed requests
timeoutnumber5000Request timeout in milliseconds

Sandbox

Set environment to 'sandbox' to test against the Kelviq sandbox environment:
<KQProvider
  promotionId="YOUR_PROMOTION_ID"
  accessToken="YOUR_SANDBOX_ACCESS_TOKEN"
  environment="sandbox"
>
  {/* ... */}
</KQProvider>

KQBanner

Displays a location-aware promotional banner. The banner message is configured in the Kelviq dashboard and supports template variables that are automatically replaced with real data.
import { KQBanner } from '@kelviq/react-promotions-ui';

// Basic — uses styles from the dashboard
<KQBanner />

// With local style overrides
<KQBanner
  backgroundColor="#1a1a2e"
  fontColor="#eaeaea"
  borderRadius="8px"
  fontSize="14px"
  addCloseIcon={true}
  className="my-banner"
  onClose={() => console.log('Banner closed')}
/>

Props

PropTypeDefaultDescription
backgroundColorstring(from API)Banner background color
fontColorstring(from API)Banner text color
borderRadiusstring(from API)Banner border radius
fontSizestring(from API)Banner font size
unStyledboolean(from API)If true, no default styles are injected
addCloseIconboolean(from API)Show a close button on the banner
classNamestring''Custom CSS class name
onClose() => voidCallback fired when the banner is closed
Props override the corresponding values returned by the API. If you don’t pass a prop, the dashboard-configured value is used.

Template variables

The banner message (configured in the dashboard) supports these placeholders:
VariableReplaced withExample
{country}Visitor’s country nameUnited States
{country_flag}Country flag image (CDN-hosted SVG)🇺🇸 (rendered as <img>)
{coupon_code}The discount coupon codeSAVE20
{discount_percentage}The discount percentage20
Example message:
Hello {country_flag} You're visiting from {country}! Use code "{coupon_code}" for {discount_percentage}% off.

CSS hooks

The banner adds classes to document.body that you can target in your stylesheets:
ClassAdded when
kq-has-bannerThe banner is visible on the page
/* Add top padding so content isn't hidden behind the banner */
body.kq-has-banner main {
  padding-top: 60px;
}

Unstyled mode

Set unStyled={true} to remove all default styles and apply your own CSS from scratch. Target the banner using the kq-banner CSS class or the data-testid="kq-banner" attribute.
<KQBanner unStyled={true} className="my-custom-banner" />

KQPriceFormatted

Displays a fully formatted discounted price based on the visitor’s location.
import { KQPriceFormatted } from '@kelviq/react-promotions-ui';

// Discounted price
<KQPriceFormatted price={99.99} />

// With decimals
<KQPriceFormatted price={99.99} showDecimal={true} />

// Currency code instead of symbol
<KQPriceFormatted price={99.99} currencyDisplay="code" />

Props

PropTypeDefaultDescription
pricenumberRequired. The product price
displayPricenumberThe price shown for original display (used with isOriginalDisplay)
isOriginalDisplaybooleanfalseRenders as strikethrough original price for comparison
classNamestring''Custom CSS class name
currencyDisplay'symbol' | 'code' | 'name''symbol'How the currency is displayed
showDecimalbooleanfalseWhether to show decimal digits
minimumDecimalDigitsnumber2Minimum decimal digits when showDecimal is true
maximumDecimalDigitsnumber2Maximum decimal digits (max 2)

Original + discounted price

Show a strikethrough original price next to the discounted price:
{/* Original price (strikethrough) */}
<KQPriceFormatted
  price={99.99}
  displayPrice={99.99}
  isOriginalDisplay={true}
  showDecimal={true}
/>

{/* Discounted price */}
<KQPriceFormatted price={99.99} showDecimal={true} />

Granular price components

Use these components individually to build custom price layouts with full styling control. All components must be rendered inside a KQProvider.

KQPriceInteger

Displays just the integer part of the discounted price.
import { KQPriceInteger } from '@kelviq/react-promotions-ui';

<KQPriceInteger price={99.99} />
PropTypeDefaultDescription
pricenumberRequired. The product price
classNamestring''Custom CSS class name

KQPriceDecimal

Displays just the decimal portion of the discounted price.
import { KQPriceDecimal } from '@kelviq/react-promotions-ui';

<KQPriceDecimal price={99.99} />
PropTypeDefaultDescription
pricenumberRequired. The product price
classNamestring''Custom CSS class name
minimumDecimalDigitsnumber2Minimum decimal digits
maximumDecimalDigitsnumber2Maximum decimal digits (max 2)

KQPriceDecimalSeparator

Renders the locale-specific decimal separator (e.g. . or ,).
import { KQPriceDecimalSeparator } from '@kelviq/react-promotions-ui';

<KQPriceDecimalSeparator price={99.99} />
PropTypeDefaultDescription
pricenumberRequired. The product price
classNamestring''Custom CSS class name

KQPriceCurrencySymbol

Renders the currency symbol (e.g. $, , ).
import { KQPriceCurrencySymbol } from '@kelviq/react-promotions-ui';

<KQPriceCurrencySymbol />
PropTypeDefaultDescription
classNamestring''Custom CSS class name

KQPriceCurrencyCode

Renders the currency code (e.g. USD, EUR, INR).
import { KQPriceCurrencyCode } from '@kelviq/react-promotions-ui';

<KQPriceCurrencyCode />
PropTypeDefaultDescription
classNamestring''Custom CSS class name

Custom price layout example

Combine granular components to build a fully custom price display:
import {
  KQPriceCurrencySymbol,
  KQPriceInteger,
  KQPriceDecimalSeparator,
  KQPriceDecimal,
  KQPriceCurrencyCode,
} from '@kelviq/react-promotions-ui';

<div className="custom-price">
  <KQPriceCurrencySymbol />
  <KQPriceInteger price={99.99} />
  <KQPriceDecimalSeparator price={99.99} />
  <KQPriceDecimal price={99.99} />
  <span className="currency-code">
    <KQPriceCurrencyCode />
  </span>
</div>

Complete example

import {
  KQProvider,
  KQBanner,
  KQPriceFormatted,
  KQPriceCurrencySymbol,
  KQPriceInteger,
  KQPriceDecimalSeparator,
  KQPriceDecimal,
} from '@kelviq/react-promotions-ui';

function PricingPage() {
  return (
    <KQProvider
      promotionId="YOUR_PROMOTION_ID"
      accessToken="YOUR_ACCESS_TOKEN"
    >
      {/* Promotional banner */}
      <KQBanner />

      {/* Formatted price with original + discounted */}
      <div className="pricing">
        <span className="original">
          <KQPriceFormatted
            price={99.99}
            displayPrice={99.99}
            isOriginalDisplay={true}
            showDecimal={true}
          />
        </span>
        <span className="discounted">
          <KQPriceFormatted price={99.99} showDecimal={true} />
        </span>
      </div>

      {/* Custom price layout with granular components */}
      <div className="custom-price">
        <KQPriceCurrencySymbol />
        <KQPriceInteger price={49.99} />
        <KQPriceDecimalSeparator price={49.99} />
        <KQPriceDecimal price={49.99} />
      </div>
    </KQProvider>
  );
}

Support

For technical support and questions, reach out at hi@kelviq.com.