Installation to React or NextJS applications

For React and NextJS applications, it's best to use use our React package. This package provides a React component that can be easily used. NextJS integration has a slightly different procedure, see below.

Please note, this page is for package version 2.0.0 and higher. Check the legacy version page if you use version 1.

React component setup

1. Install the React NPM package

npm install react-product-fruits --save

2. Find the right place where to put the component

This is very important. The <ProductFruits /> component must be inserted to the top-most place in your application tree that is possible. For example, if you use React Router, do not put it to every route. Put it to the <Routes> component directly (not to <Route />) or completely outside of it.

3. Import the package

For React applications, use standard import

import { ProductFruits } from 'react-product-fruits';

For NextJS applications, use dynamic import. This is needed because NextJS uses server-side rendering, but Product Fruits is only a frontend component.

const ProductFruits = dynamic(
    () => import('react-product-fruits').then(mod => mod.ProductFruits),
    { ssr: false }
)

4. Use the component

The component requires a few props. You have to provide the ID of your workspace, current language code, and current user information.

  • workspaceCode - code of your workspace, you will find it in the Installation section in the Product Fruits administration
  • language - 2 letter ISO language code, it has to match values you specified before in Product Fruits administration (see Workspace settings -> Supported Languages). The language code must be lowercase.
  • user - a user information object with at least the username property filled
  • config - an optional config object, see here for available options
  • debug - if set to true, you'll recieve debug info in your browser console
  • dontDestroy - PF won't be destroyed when the component is unmounted. This can be used when multiple mountings/unmountings happen during your rendering cycle. In this case, when you want to destroy Product Fruits manually (e.g. when the user logs out or switches to a different application language), call window.productFruits.services.destroy().

For React applications, use the component as usual:

<ProductFruits workspaceCode="YOUR_WORKSPACE_CODE" language="LOWER-CASE ISO-2 CODE OF LOCALIZATION LANGUAGE" user={userInfo} />

For NextJS applications, check if the window global variable exists.

{global.window && <ProductFruits workspaceCode="YOUR_WORKSPACE_CODE" language="LOWER-CASE ISO-2 CODE OF LOCALIZATION LANGUAGE" user={userInfo} />

Routing in NextJS

Product Fruits can randomly fail to detect URL changes in NextJS. You can see multipage tours randomly stopping. The solution is to turn off the default URL detection and notify Product Fruits about the page change. 

First, disable the route change detection by passing the disableLocationChangeDetection option to the component:

<ProductFruits workspaceCode="YOUR_WORKSPACE_CODE" language="LOWER-CASE ISO-2 CODE OF LOCALIZATION LANGUAGE" user={userInfo} config={{ disableLocationChangeDetection: true }} />

Then, in your _app.tsx file, outside of the App component, add this snippet:

import Router from 'next/router'

Router.events.on('routeChangeComplete', () => {
    window.productFruits.pageChanged();
});

// Here comes the App component function
//function App({ Component, pageProps }: AppProps) {

User information object

The user prop takes a user information object. You must pass at least the username property that holds the current user's unique identifier (e.g. email, username, user ID). If you don't want to transfer real usernames to Product Fruits, you can hash them (i.e. MD5, SHA1).

Product Fruits can also show different content based on different user attributes. These attributes can hold any primitive value (number, string, array). It is not required to provide any other identification than the user's unique identifier, but often more is needed - typically for segmentation purposes. To help you get started, there are some built-in attributes that you can provide as props on the ProductFruits component:

  • email - optional, string
  • firstname - optional, string
  • lastname - optional, string
  • signUpAt - optional, (can be any format but we recommend the ISO 8601 JSON DateTime format)
  • role - optional, string

You can also include other custom attributes. These have to be provided through props subobject. See the full working example below.

Working with Product Fruits JS API

If you want to use Product Fruits API in your React application, it's best to use our useProductFruitsApi hook.

useProductFruitsApi(api => {
        if (your_dep == "something") {
            api.tours.tryStartTour(tourId);
        }
}, [your_dep]);

Dynamic CSS generation

If your project uses a library for CSS scoping (like Emotion), it probably generates dynamic CSS classes like css-a9fp3q. This will make issues with tours and hints as they use CSS selectors for targeting.

If there are no other stable attributes, consider this.

Full working example

You can check out a simple example of a React application using Product Fruits. The example uses React Context and React Router, so it simulates typical use cases.

See the GitHub repository

Here is a short showcase of working integration:

import React from 'react';
import { ProductFruits } from 'react-product-fruits';

export class App extends React.Component {
  render () {
    const { appUser } = this.props; // you have to provide user information from your store
    
    const userInfo = {
      username: appUser.username,
      email: appUser.email,
      firstname: appUser.firstname,
      lastname: appUser.lastname,
      signUpAt: appUser.signUpAt,
      role: appUser.role,
      props: { customProperty1: 123 }
    };

    return (
      <div>
        <ProductFruits workspaceCode="YOUR_WORKSPACE_CODE" language="LOWER-CASE ISO-2 CODE OF LOCALIZATION LANGUAGE" user={userInfo} />
      </div>
    );
  }
}