@digitaloptgroup/cms-react v0.0.1-dev-preview.33
Digital Optimization Group - Headless CMS for A/B Testing - React SDK
This library is a developer preview.
It provides an easy and powerful way to implement A/B testing with React
. It is made to work with Digital Optimization Groups' Headless CMS and requires an account on our platform.
Signing up for a developer preview requires an invite. If you would like to join the waiting list for access please email us at preview@digitaloptgroup.com.
The SDK includes the following features:
- Simple implementation with a render prop
- A/B/n testing of arbitrary data structures
- A/B/n testing of
React
components - Viewport exposure tracking of all variations
- Wide range of client metrics automatically collected and associated with variations
Installation
The DigitalOpt Group React SDK can be installed and added to the project specific dependencies by running the following command:
npm install --save @digitaloptgroup/cms-react
The SDK provides the following set of Providers
and Render Props
:
- AbTesting
- Feature
- Feature.Track
- withOutcome
- withPathChange
- withCaughtError
Documentation
https://docs.digitaloptgroup.com
AbTesting Provider
Digital Optimization Groups' React SDK makes uses of a provider to inject all the required code into your application.
The provider is required for the correct usage of the SDK. Its main purposes are:
- Make a connection to the public API
- Provide RealTime development feature
- Initialize analytics tracking
The provider should be placed at the root
of your application and expect a set of configuration properties (explained below):
Props
The React SDK requires a set of keys and configurations required to connect the Client Application with the Public API.
projectId (required) The Application Id or Project Id given to you by Digital Optimization Group when creating your account.
vid (optional) Internally the API sets a cookie with a unique ID for each user. This cookie is used to assure consistent assignment of variations. You may optionally pass in your own unique visitor identifier that will be used to provide assignments.
rid (optional) Unique request Id. If you are deploying your application into the DigitalOptADN you should not set this as it will be done for you automatically.
startTimestamp (optional) Server timestamp of request Id creation time. If you are deploying your application into the DigitalOptADN you should not set this as it will be done for you automatically.
Usage
import { AbTesting } from "@digitaloptgroup/cms-react";
ReactDOM.render(
<AbTesting projectId="your-app-or-project-id">
<App />
</AbTesting>,
document.getElementById("root")
);
Components
All components provided by SDK, are written as Render Props or Higher Order Components, to provide a full set of features, with minimal impact on your app.
There are currently 2 render props, and they are:
- Feature
- Feature.Track
And 3 higher order components:
- withCaughtError
- withOutcome
- withPathChange
Feature
This component fetches the data related to a Schema from the CMS (Feature Schema Documentation).
Props
Props that can be passed to the Feature
component.
queryName (required)
The root entrypoint to query your API. This is defined in the CMS when creating a new Schema.
args (as required by Schema type)
When defining a Schema it may be created with one or more parameters, such as path
for blog posts, lang
for localization, or sku
for products. Providing these to the Feature
component will allow you to query for a specific Feature that implements a given Schema.
Provided Props
Props passed from Feature
to the user's render prop function.
error Provided in the event of an error.
type Error = null | { code: number; message: string };
Note on serving 404 pages If the given combination of
queryName
andargs
does not result in a feature this will return a 404 error with the following object:
{code: 404, message: "404 - Feature not found"}
This is useful if you are serving pages, such as blog posts, and would like to dynamically show your visitors 404 pages when a page does not exist.
isLoading A boolean prop indicating feature loading.
type IsLoading = boolean;
variation The variation assigned to a given user for the requested feature. This can be either an object containing the properties defined by the feature's schema or it can be a list of variations.
type Variation =
| FeatureSchema
| Array<{ tracking: Tracking; variation: FeatureSchema }>;
type FeatureSchema = { [key]: any };
tracking The tracking object associated with a given variation.
type Tracking = {
releaseId: string;
featureId: string;
variationId: string;
exposureId: string;
};
Usage
import { Feature } from "@digitaloptgroup/cms-react";
function App() {
return (
<Feature queryName="helloWorld">
{({ error, isLoading, variation, tracking }) => {
if (variation) {
const { image, headline, subhead } = variation;
return (
<div>
<img src={image.url} />
<h1>{headline}</h1>
<h4>{subhead}</h4>
</div>
);
} else if (isLoading) {
return <div>Loading...</div>;
} else if (error) {
return (
<div>
{error.code} : {error.message}
</div>
);
}
}}
</Feature>
);
}
Feature.Track
This component provides viewport tracking for assigned variations including proportion of exposure and time in viewport.
Props
Props that MUST be passed to the Feature.Track
component.
releaseId (required) This Id represents a hash of the entire release and provides integrity when analyzing data by assuring it is always possible to know what other elements may have been under test at any given time.
featureId (required) Represents a hash of all the variations for a given feature in a given release. It provides integrity to know what other variations where under test for a given feature.
variationId (required) A hash of the variation, assuring integrity of knowing the exact content for a given variation.
exposureId (required) Not currently used, but still required. This may be used in the future for more granular exposure tracking than provided at the variation level (like by fields).
Provided Props
Props passed from Feature.Track
to the user's render prop function.
trackingRef A React ref that MUST be attached to a root DOM element surrounding the implementation of a given variation.
Usage
import { Feature } from "@digitaloptgroup/cms-react";
function App() {
return (
<Feature queryName="helloWorld">
{({ error, isLoading, variation, tracking }) => {
if (variation) {
return (
<Feature.Track {...tracking}>
{({ trackingRef }) => {
return <div ref={trackingRef}>{/*...*/}</div>;
}}
</Feature.Track>
);
}
/* ... */
}}
</Feature>
);
}
Higher Order Components for Metrics
Refer to A/B Testing Analytics for a full overview of metrics automatically and manually tracked by this SDK.
This section will cover the manual tracking details from the SDK.
The SDK provides a set of higher order component that offers the possiblity of wrapping your components to track additional analytics information not tracked automatically.
The use of these HOCs requires the main application to wrapped within the AbTesting provider, but it can be applied to any of the components provided within the SDK. It will also work with normal React components.
Examples Record add to cart events, page views, searches, checkouts, and more.
withPathChange
This higher order component passes the pathChange
prop to it's wrapped child, allowing for page view metrics to be associated with A/B test variations.
Props
None
Provided Props
Props passed to the wrapped component.
pathChange A function that can be used to track pageviews.
type PathChange = (pathname: string) => void;
Usage
import { withPathChange } from "@digitaloptgroup/cms-react";
class BlogPost extends React.Component {
componentDidMount() {
this.props.pathChange(this.props.location.pathname);
}
componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
this.props.pathChange(this.props.location.pathname);
}
}
render() {
/*...*/
}
}
const BlogPostWithPageTracking = withPathChange(BlogPost);
withOutcome
This higher order component passes the outcome
prop to it's wrapped child, allowing for custom outcomes to be associated with A/B test variations.
Props
None
Provided Props
Props passed to the wrapped component.
outcome A function that can be used to track custom outcomes. Any outcome can be used to evaluate a given A/B test.
type Metadata = Array<{ key: string; value: string }>;
type Outcome = (name: string, metadata: Metadata) => void;
Naming Outcomes We recommend picking and sticking with a consistent naming convention for outcomes. One that we like is the Object / Action naming convention. For example:
- cartAddItem
- cartRemoveItem
- searchAddFilter
- searchEnterPhrase
- productView
Usage
import { withOutcome } from "@digitaloptgroup/cms-react";
class ProductItem extends React.Component {
cartAddItem = (sku, price) => {
const name = "cartAddItem";
const metadata = [
{ key: "sku", value: sku },
{ key: "price", value: price }
];
this.props.outcome(name, metadata);
};
render() {
/*...*/
}
}
const ProductItemWithOutcome = withOutcome(ProductItem);
withCaughtError
This higher order component passes the caughtError
prop to it's wrapped child, allowing for caught errors to be associated with A/B test variations. This can be useful for monitoring A/B tests and becoming notified of potential bugs or problems with a particular test variation.
Props
None
Provided Props
Props passed to the wrapped component.
caughtError A function that can be used to track errors your application catches.
type CaughtErrorMetadata = Array<{ key: string; value: string }>;
type CaughtError = (metadata: CaughtErrorMetadata) => void;
Usage
import { withCaughtError } from "@digitaloptgroup/cms-react";
class CartCheckout extends React.Component {
completeOrder = () => {
stripe.createSource(this.card).then(result => {
if (result.error) {
const metadata = [
{ key: "location", value: "stripe.createSource" },
{ key: "error", value: error.message }
];
this.props.caughtError(metadata);
/* ... */
} else {
/*...*/
}
});
};
render() {
/*...*/
}
}
const CartCheckoutWithErrorReporting = withCaughtError(CartCheckout);
Server side rendering
If you'd like to do server side rendering just reach out to us.
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago