@buddy-technology/offer-component
v1.4.0
Published
--- React component for adding [Buddy's](https://buddy.insure) Insurance Gateway
Downloads
945
Readme
Buddy Offer Component
React component for adding Buddy's Insurance Gateway
Requirements
Contact Buddy to obtain a partnerID
and compatible ions
for your specific use case.
Installation
Install it from npm and include it in your React build process
npm install @buddy-technology/offer-component
or
yarn add @buddy-technology/offer-component
Basic Usage
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
function App() {
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement ion="MY_ION" partnerID="my-partner-id" stage="STAGING" />
</div>
);
}
export default App;
Combined with useConfig hook
import React from 'react';
import BuddyOfferElement, { useConfig } from '@buddy-technology/offer-component';
function App() {
const { config, isLoading } = useConfig('https://config-domain.com/config.js');
if (isLoading || !config) {
return null;
}
// grab relevant properties from config
const theme = config.themeBase;
const data = config.data;
const handleUserEvents = config.userEvents;
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
stage="staging"
theme={theme}
data={data}
onUserEvent={handleUserEvents}
/>
</div>
);
}
export default App;
Props
| Option Name | Type | Default | Description
| --- | --- | --- | --- |
| *partnerID | string | | The partnerID assigned to you from Buddy |
| *ion | string | | The ion ID for the product to be presented |
| stage | enum | "STAGING" | One of: "STAGING"
, "PRODUCTION"
. Set to "STAGING"
(default) for testing and development. |
| viewType | enum | "paginated"
| Sets how the offer element is displayed. One of: "paginated"
, "single-form"
, "offer-only"
. See View types for details.|
| data | object | | Customer or policy data to pre-load the offer with. Refer to specific ION documentation for the data structure. |
| theme | object | |The theme object for passing in styles and color palettes |
| onUserEvent | function | | A callback for tracking user behavioral data. See Capturing Data for details. |
| includeCheckout | boolean | true
| Toggles whether to render the secure checkout. |
| onOptIn | function | | The callback fired when a user opts into an offer. See Buddy's Partner API docs for details on how to complete the transaction.|
| onOptOut | function | | The callback fired when a user opts out of the offer. |
*required
View Types
Buddy's Offer Element comes in three different view types:
- paginated (default) - A paginated form where users click through to the next section.
- single form - A single form where all fields are displayed in the same, scrollable view.
- offer only - View for displaying just the insurance offer with a quote and checkbox that fires
onOptIn
when checked andonOptOut
when unchecked (see For full stack apps for more info). NOTE: Offer-Only implementations are meant to be rendered in a controlled environment with necessary data passed into it, and will require a payment integration for checkout (see Buddy's Partner API docs). If any fields are missing or invalid, a step-through form will render with the individual views that include the needed fields. Views with satisfied fields will be skipped. Once users rectify any needed info, they will land on the offer only screen.
Checkout
For client-side only apps
The embed widget's default mode includes a full checkout. Customers can go through the entire flow through to a secure purchase and policies will be delivered directly to their inbox.
To explicitly set the widget to include checkout, set the includeCheckout
property to true
.
For full stack apps
In server side and full-stack applications where customers are already purchasing other products, it's best to exclude the secure checkout built into the widget so customers can purchase their insurance alongside any other products as part of a single transaction. A backend integration (See Buddy's Partner API docs) is required in order to complete the transaction.
To use this mode, set includeCheckout
to false
, or set viewType to offer-only
.
When users opt in, the onOptIn
callback is fired with the completed application object. If a user opts out, onOptOut
will be called.
// simple paginated example to collect data
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
import { handleAddToCart, handleRemoveFromCart } from './myApi';
function App() {
const handleAddToCart = (payload) => {
handleAddToCart(payload)
};
const handleRemoveFromCart = (payload) => {
handleRemoveFromCart(payload)
};
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
viewType="paginated"
includeCheckout={false}
onOptIn={handleAddToCart}
onOptOut={handleRemoveFromCart}
stage="PRODUCTION"
/>
</div>
);
}
export default App;
// example using offer-only and passing in customer/policy data
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
import { handleAddToCart, handleRemoveFromCart } from './myApi';
// passing down data as prop in this example
function App({ userAndPolicyData }) {
const handleAddToCart = (payload) => {
handleAddToCart(payload)
};
const handleRemoveFromCart = (payload) => {
handleRemoveFromCart(payload)
};
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
viewType="offer-only"
data={userAndPolicyData} // data is passed in, if any fields are invalid, they will be displayed to user to rectify before purchasing.
onOptIn={handleAddToCart}
onOptOut={handleRemoveFromCart}
stage="PRODUCTION"
/>
</div>
);
}
export default App;
Pre-filling Data
It's a best practice to pass in any customer and policy data that has already been collected to optimize user experience. Unless viewType is offer-only
, users will be able to see and edit any data that is passed.
Data follows the application object structure. Refer to your specific ION (or offering) documentation.
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
function App() {
const data = {
customer: {
firstName: 'customer first name',
lastName: 'customer last name',
address: {
line1: 'street address',
city: 'city',
state: 'state',
zip: 'zip',
}
},
policy: {
startDate: '12/31/2022',
}
};
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
data={data}
stage="PRODUCTION"
/>
</div>
);
}
export default App;
Styling
Buddy's offer element supports extensive visual customization, allowing you to seamlessly match the design of your site with the theme prop.
Pick a base theme and color palette: Quickly get running by picking the prebuilt theme and palette that most closely resembles your website.
Customize even further by adding overrides: Virtually any property can be further customized using CSS object styling.
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
function App() {
const customTheme = {
baseTheme: "base",
palette: "buddy",
overrides: {
webFonts: [
'https://fonts.googleapis.com/css2?family=Rubik:wght@700&display=swap',
],
styles: {
h1: {
color: 'var(--color-text-primary)',
fontFamily: 'Rubik, sans-serif',
fontSize: '2rem',
'@media (min-width: 992px)': {
fontSize: '3rem',
},
'&:hover': {
boxShadow: 'none',
backgroundColor: '#FBF9EF',
},
},
body: { color: '#0A242D' },
'.input-text': {
border: 'none',
color: '#333333',
}
},
colors: { textPrimary: '#0A242D' },
},
};
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
theme={customTheme}
stage="PRODUCTION"
/>
</div>
);
}
export default App;
Color Palettes
We currently offer two color palettes to start with (with more coming soon!).
Base:
primary: '#000000',
secondary: '#254E70',
tertiary: '#848484',
negative: '#e45b78',
positive: '#A3D9B1',
textPrimary: '#000',
textSecondary: '848484',
backgroundPrimary: '#fff',
backgroundSecondary: '#7d8387',
Buddy:
primary: '#DC5648',
secondary: '#0A242D99',
tertiary: '#46460E33',
negative: '#D62719',
positive: '#A3D9B1',
textPrimary: '#0A242D',
textSecondary: '#0A242D99',
backgroundPrimary: 'linear-gradient(#D6F1F2, #F8F6D2)',
backgroundSecondary: '#FBF9EF',
Overrides
The overrides object consists of three major properties:
webFonts
: An array of string urls for web fonts. Note: if using web fonts, it is still necessary to set the fontFamily
property on any elements using that particular webfont.
styles
: A CSS styles object with any CSS overrides on a given theme. Styles will overwrite existing theme styles. Media queries and child selectors can be accessed as a string key name, and nested within a given selector (see the example above). Component classes can also be manipulated within the styles object.
colors
: A colors object will override any of the color properties in the table below:
| Key | Where its used | | --- | --- | | primary | graphics, call-outs, primary buttons | | secondary | focused borders, accents | | tertiary | inactive accents | | negative | error messages (note: this is currently set to "accessible red." be mindful of accessibility when overriding this property) | | positive | success messages | | textPrimary | primary body copy | | textSecondary | secondary copy, accents | | backgroundPrimary | main background (containers) | | backgroundSecondary | secondary backgrounds |
Classes and Components
Some components can be directly modified by accessing their class names in the theme object. See the full list of component class names below.
var customTheme = {
style: {
h1: { fontSize: 36 },
'.button-primary': {
// custom styles
},
},
};
Available Classes
- card
- button-primary
- button-secondary
- input-text
- input-invalid
- input-select
- input-label
- input-label-invalid
- offer-container
- field-container
- view-container
Capturing data
You can hook any CRM or analytics platform into the Buddy offer-element using the onUserEvent
hook.
onUserEvent(eventType: string, data: object) ⇒ void
The onUserEvent
hook property allows you to pass in a custom function to embed your analytics of choice. Simply pass in a callback to the onUseEvent
option, and you will get the following 2 parameters:
- eventType: string denoting the type of event that fired (ex: "onViewChange")
- data: object with internal data regarding the event. All data objects include a timestamp property.
Quick example
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
function App() {
const handleUserEvent = (payload) => {
// logs an object with eventType and data to the console
console.log(payload)
};
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
viewType="offer-only"
onUserEvent={handleUserEvent}
stage="PRODUCTION"
/>
</div>
);
}
export default App;
Event types and data fired:
We capture several user-driven events and each has different available pieces of data associated with it. Look closely at the list below to determine which events you want to capture and how to use the data.
onViewChange
Triggers when users click to a new screen in a paginated view mode.
data returned
| Name | Type | Description |
|-----------|--------|---------------------------------------------------------|
| viewId
| string | the id of the current view |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onScrollToView
Triggers when or scroll to a section in single-page view mode.
data returned
| Name | Type | Description |
|-----------|--------|---------------------------------------------------------|
| viewId
| string | the id of the current view |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onQuote
Triggers when the app displays retrieves a quote for the policy
data returned
| Name | Type | Description |
|-----------|--------|-----------------------------------------------------------------------------------|
| pricing
| number | if successful, the price of the policy |
| error
| string | if unsuccessful, a message explaining the type of error encountered when attempting to quote |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onCheckout
Triggers during the check out process
data returned
| Name | Type | Description |
|--------------------|--------|-----------------------------------------------------------------------------------|
| checkoutStatus
| enum | one of ['start', 'success', 'error']
|
| premium
| number | the total premium of the purchase |
| error
| string | if unsuccessful, a message explaining the type of error encountered |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onFocus
Triggers when an input is focused
data returned
| Name | Type | Description |
|------------------|--------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onBlur
Triggers when an input is blurred
data returned
| Name | Type | Description |
|------------------|--------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onRadioSelection
Triggers when a radio button is selected
data returned
| Name | Type | Description |
|-------------|--------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| value
| any | the value of the selected radio |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onSlide
Triggers when a slider input is changed
data returned
| Name | Type | Description |
|-------------|--------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| value
| any | the value of the selected radio |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onCheckboxSelection
Triggers when a checkbox is selected
data returned
| Name | Type | Description |
|--------------|---------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| checked
| boolean | whether the box is checked/unchecked |
| value
| string | the label of the selected checkbox |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onBlur
Triggers when an input is blurred
data returned
| Name | Type | Description |
|------------------|--------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onValidationError
Triggers when an input is triggered as invalid
data returned
| Name | Type | Description |
|----------------------|--------|---------------------------------------------------------|
| elementId
| string | the id of the invalid field/input |
| validationError
| string | the type of validation error encountered |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onExternalLink
Triggers when an input is triggered as invalid
data returned
| Name | Type | Description |
|----------------------|--------|---------------------------------------------------------|
| externalLinkUrl
| string | the url of the link |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
onOptIn
Triggers when a user opts into an 'offer-only' insurance offer
data returned
| Name | Type | Description |
|----------------------|--------|---------------------------------------------------------|
| viewId
| string | the id of the view: 'offer-only' |
| premium
| number | the total premium of the purchase |
| partnerId
| string | the partner id used for the offer |
| timestamp
| number | the timestamp when the event occurred in milliseconds |
Google Analytics example
import React from 'react';
import BuddyOfferElement from '@buddy-technology/offer-component';
function App() {
/* This is an example of how you could use these events
your usage may vary depending on your analytics systems */
const handleUserEvent = (e) => {
// this block shows a condition looking for checkout and success,
// this is a completed purchase using the GA 'purchase' event for conversion
if (e.eventType == "onCheckout" && e.data.checkoutStatus == "success") {
gtag("event", "purchase", {
transaction_id: e.data.orderID,
value: e.data.premium,
items: [{
item_id: "SKU_12345",
item_name: '${ion}',
currency: "USD",
price: e.data.premium,
}]
});
}
// This block tracks which views are displayed
// this is configured to use the built-in GA event 'screen_view'
if (e.eventType == "onViewChange") {
gtag('event', 'screen_view', {
'app_name': 'in-offer-element',
'screen_name': e.data.viewID
});
}
// This block tracks when quotes are made
// This is configured to use a custom event and captures a custom dimension
if (e.eventType == "onQuote") {
gtag('event', 'quote', {
'app_name': 'in-offer-element',
'price': e.data.pricing,
});
}
}
};
return (
<div id="app">
<h1>My App</h1>
<BuddyOfferElement
ion="MY_ION"
partnerID="my-partner-id"
viewType="offer-only"
onUserEvent={handleUserEvent}
stage="PRODUCTION"
/>
</div>
);
}
export default App;