NAV Navbar

Userflow.js Reference

Userflow.js should be installed in your web app or website. It's responsible for identifying your users with Userflow and showing flows, checklists and more when appropriate.

Follow us on Twitter for Userflow.js announcements.

Quick links

Quick access to methods that you'll probably need:

Method Purpose
userflow.init() Initialize Userflow.js with your Token
userflow.identify() Identify a user
userflow.group() Associate current user with a group
userflow.track() Track an event

Installation

Install userflow.js via npm

Install Userflow.js via npm:

npm install userflow.js

Or, install via Yarn

yarn add userflow.js

We recommend using the userflow.js npm package as it offers the best developer experience:

See also Userflow.js installation for an alternative installation method via a plain <script> tag.

Quick start

import userflow from 'userflow.js'

userflow.init('<USERFLOW_TOKEN>')
userflow.identify('<USER_ID>', {
  name: '<NAME>',
  email: '<EMAIL>',
  signed_up_at: '2019-06-14T16:25:49Z',
})

Put this code in your app where it has access to the current user's information.

Replace all placeholders (e.g. <USERFLOW_TOKEN> and <USER_ID>) with real values.

Grab your Userflow.js Token under Settings -> Environments. Note that if you have multiple environments (e.g. Production and Staging) that each environment has a unique token.

The userflow object

Import the userflow object:

import userflow from 'userflow.js'

The userflow.js npm package is a thin wrapper around the real Userflow.js, which is loaded from our CDN. This way, you can interact with the imported userflow object immediately. On the first method call, the real Userflow.js will automatically be loaded (asynchronously) and injected into the current page. Method calls are automatically queued by the userflow object.

The real Userflow.js script is a small script (currently <20 KB gzipped) that contains the bare minimum to identify users and check if they have any active flows. Additional UI code and styles will only load if the user has any active flows. This is to have as small an impact on your page's load time as possible.

If you've installed Userflow.js via a <script> tag, you can access the object via window.userflow. Just be careful that it may not be loaded yet (which is why the userflow.js npm package is recommended!).

Attributes

Example of using all the possible data types (these will all be inferred as expected):

userflow.identify('123456', {
  string: 'Just a string',
  always_true: true,
  always_false: false,
  integer_number: 42,
  decimal_number: 1234.56,
  used_datetime_at: '2019-12-03T12:34:56.123Z',
})

Remove an attribute:

userflow.updateUser({
  phone_number: null,
})

Explicitly setting data_type:

userflow.identify('123456', {
  // This will be consumed as a string, even though its value
  // is a number here
  phone: {set: 12345678, data_type: 'string'},
})

Using set_once:

userflow.identify('123456', {
  coupon_code: {set_once: generate_onetime_coupon_code()},
})

Using add and subtract:

userflow.updateUser({
  widget_count: {add: 1},
  total_revenue: {add: 1234.56},
  days_left: {subtract: 1},
})

Several methods accept an attributes dictionary, which represents arbitrary information about objects such as users and events. You can use this to, for example, store a user's name or their date of sign-up, or to decorate events with e.g. which billing plan was selected. These attributes can then be used within Userflow to segment users or personalize their flows.

When updating objects with attributes, the values in the attributes dictionary can be literal values (string, boolean, number), which just sets the attributes to the given values.

If an attribute value is null, the attribute will be removed from the object.

You can also specify an operation object instead of a literal value. This operation object can contain the following keys (note that exactly one of set, set_once, add or subtract must be set):

Key Description
set String/number/boolean - Sets the attribute to this value. This is the same as using literal values, except this way you can explicitly set the data_type, too.
set_once String/number/boolean - Sets the attribute to this value, but only if the user doesn't already have a value for this attribute.
add Number - Adds this value to the attribute's current value. If the user does not have the attribute yet, the given number will be added to 0. Only works on number attributes.
subtract Number - Same as add, but subtracts the given number instead. To subtract, you either supply a negative number to add, or a positive number to subtract.
data_type String - Explicitly tells Userflow what data type to use. Can be one of: string, boolean, number, datetime. You usually don't have to set this, as Userflow will infer the right data type depending on the values you supply.

Attribute names (they keys of attributes objects) must consist only of a-z, A-Z, 0-9, underscores, dashes and spaces. We recommend using snake_case everywhere though. Attributes' human-friendly display names (e.g. "Signed Up" for signed_up_at) can also be configured in the Userflow UI.

Setup

init()

userflow.init('bmztslyu5zgujmcvna34mggj44')

Initializes Userflow.js to target your company. Must be called once (per page load) before you make any other call.

Parameters

Parameter Description
token String, required - Your Userflow.js Token, which you can find under Settings -> Environments. Note that if you have multiple environments (e.g. Production and Staging) that each environment has a unique token.

Users

Users are the people using your application. Userflow keeps track of your users, so we can determine which flows to show them, and remember which flows they've already seen.

identify()

Example of sending the recommended attributes:

userflow.identify('123456', {
  name: 'Jane Smith',
  email: 'jane@example.com',
  signed_up_at: '2019-06-14T16:25:49Z',
})

Minimal example of sending only userId:

userflow.identify('123456')

Identifies the current user with Userflow. You should call this once on any page load where a user is signed in.

If attributes is set, they will be merged into the user's existing attributes in Userflow. Any attributes you leave out will be left as-is in Userflow.

It's up to you which attributes you want to send to Userflow. The only required argument is userId. Make sure not to send any sensitive data such as passwords. We recommend sending the name and email attributes so you can easily tell users apart in Userflow without relying on IDs only, and signed_up_at, which is often used in flow start conditions.

If the user has any active flows, they will be displayed. If the user matches any flows' start conditions, they may be started.

Parameters

Parameter Description
userId String, required - The user's ID in your database.
attributes Object, optional - Attributes to update for the user. See Attributes. These attributes can be used in flow content and conditions to personalize the user experience.

Returns

A Promise that resolves once the identify call succeeds.

identifyAnonymous()

Example of identifying an anonymous user and tagging them with a custom website_lead attribute, so they can be targeted by flows:

userflow.identifyAnonymous({
  website_lead: true,
})

Same as userflow.identify(), except Userflow.js will automatically assign the current user a unique ID. This ID will be stored in the user's localStorage, and will be reused on reloads.

You should only use this for anonymous users, who are not signed into your app. If they are signed in, please use userflow.identify() with their real user ID.

Parameters

Parameter Description
attributes Object, optional - Attributes to update for the user. See Attributes. These attributes can be used in flow content and conditions to personalize the user experience.

Returns

A Promise that resolves once the identify call succeeds.

isIdentified()

userflow.isIdentified() // true or false

Check if a user has been identified.

Returns

true if userflow.identify or userflow.identifyAnonymous has been called. false otherwise.

updateUser()

Example of updating a user's favorite color:

userflow.updateUser({
  favorite_color: 'red',
})

Updates attributes for a user that has already been identified with userflow.identify since the last page load.

Parameters

Parameter Description
attributes Object, optional - Attributes to update for the user. See Attributes.

Returns

A Promise that resolves once the update call succeeds.

reset()

userflow.reset()

Makes Userflow forget about the current user and immediately hides any active flows.

Call this when users sign out of your app.

Groups

Groups are used to group multiple users together. In your business, groups may correspond to e.g. companies, teams or departments.

Like users, groups can have attributes. Events can also be associated with groups.

With groups, you can orchestrate the flows a user sees:

Note that the Groups feature is only available in certain plans. Check your Billing page or reach out to us to ask.

group()

Example setting the current group for a user:

userflow.group('987654', {
  name: 'Acme Inc.',
  plan: 'Premium',
})

Minimal example of sending only groupId:

userflow.group('987654')

Example including membership attributes:

userflow.group(
  '987654',
  {
    name: 'Acme Inc.',
    plan: 'Premium',
  },
  {
    membership: {
      role: 'owner',
    },
  }
)

Associates the currently identified user with a group, and optionally updates the group's attributes. You should call this once on any page where the user is working on a specific group. If the user navigates to a different group, simply call userflow.group(newGroupId) again, and Userflow will switch to using that group instead.

If attributes is set, they will be merged into the group's existing attributes in Userflow. Any attributes you leave out will be left as-is in Userflow.

Parameters

Parameter Description
groupId String, required - The group's ID in your database.
attributes Object, optional - Attributes to update for the group. These attributes can be used in flow content and conditions to personalize the user experience.
options Object, optional
options.membership Object, optional - Attributes to update for the user's membership of the group. Some attributes neither belong on users, nor on groups. One example is a user's "role". A user can have different roles in different groups. A group's members can have different roles. Attributes like "role" are membership attributes. They can be used in the Userflow UI just like group attributes.

Returns

A Promise that resolves once the group call succeeds.

updateGroup()

Example of updating a group's plan:

userflow.updateGroup({
  plan: 'Pro',
})

Updates attributes for a group that has already been registered with userflow.group since the last page load.

Parameters

Parameter Description
attributes Object, optional - Attributes to update for the group. See Attributes.

Returns

A Promise that resolves once the update call succeeds.

Events

You can track events for users and groups for analytics purposes or to segment and personalize your flows.

Events tracked via Userflow.js is always associated with the current user. They can optionally be associated with groups, too.

track()

Minimal example of tracking an event when a user activates their subscription:

userflow.track('subscription_activated')

Example with attributes:

userflow.track('subscription_activated', {
  plan_name: 'plus',
  plan_price: 1234.56,
})

Track an even without associating it with the current group:

userflow.track(
  'email_changed',
  // No attributes
  {},
  // Options
  {
    userOnly: true,
  }
)

Tracks an event related to the currently identified user.

userflow.identify must have been called before calling track.

Both event names and attribute names must consist only of a-z, A-Z, 0-9, underscores, dashes and spaces. We recommend using snake_case everywhere though. Events and attributes' human-friendly display names (e.g. "Subscription Activated" for subscription_activated) can also be configured in the Userflow UI.

We recommend using event names consisting of a noun and a past-tense verb. Check out this great event naming guide by Segment.

Parameters

Parameter Description
eventName String, required - Name of the event. Examples: subscription_activated, project_created, coworker_invited. See note about event naming below.
attributes Object, optional - Attributes for the event. See Attributes.
options Object, optional - Adjust how the event should be tracked.
options.userOnly Boolean, optional - By default, when userflow.group() has been called, events are associated with both the user and the group. Set userOnly to true to not associate the event with the group. This is useful when the user performs an event that's not group-related, such as changing their own email address.

Returns

A Promise that resolves once the track call succeeds.

Flows and content

Content refers to the stuff you build in Userflow, such as flows and checklists. You can manipulate what the current user sees programmatically via Userflow.js.

start()

Start a flow and show it immediately:

userflow.start('89eff72a-d0ae-4be6-b241-1ab04e3da7cc')

Start flow, but only if the user hasn't seen it before:

userflow.start('89eff72a-d0ae-4be6-b241-1ab04e3da7cc', {once: true})

Starts a Userflow content item (flow, checklist etc.) for the currently signed-in user. The content will display immediately.

Use this to programmatically start content when something happens in your app. You could, for example, implement a button called "Show onboarding tutorial again", which users can click after signing up to go through your tutorial again.

Parameters

Parameter Description
contentId String, required - ID of the content to start. You can find the content ID in Userflow on the "Link/Embed" tab. It's also the ID you see in the URL: /app/{company}/content/{contentId}
options Object, optional
options.once Boolean, optional - If set to true, the content will only start if the user has not seen it before. If the user has already seen it before, nothing happens. Defaults to false.

Returns

A Promise that resolves once the content has been started.

endAll()

userflow.endAll()

Ends all currently active Userflow content (flows, checklists etc.), if any, for the user. The content will be hidden immediately.

If the user does not have any active content, nothing happens.

Advanced usage

on()

const listener = (visible) => {
  console.log(visible ? 'Flow is visible' : 'Flow was hidden')
}
userflow.on('flowvisibilitychange', listener)

// ...later, when no longer needed:
userflow.off('flowvisibilitychange', listener)

Registers an event listener to be called when the given eventName is triggered.

Parameters

Parameter Description
eventName String, required - Name of event to listen for. See list of supported events.
listener Function, required - Function to call when the event is triggered. Depending on the eventName, listener may receive a single argument providing more details about the event.

off()

userflow.off('flowvisibilitychange', listener)

Removes an event listener previously registered with userflow.on.

Parameters

Parameter Description
eventName String, required - Name of event. See list of supported events.
listener Function, required - Function to that was added with userflow.on.

registerCustomInput()

Example HTML markup (in your app):

<label>Fruit</label>
<div class="combo-box">
  <div class="combo-box-value">Banana</div>
  <div class="combo-box-trigger">..icon..</div>
</div>

Example Userflow.js configuration:

userflow.registerCustomInput('.combo-box-value')

It's now possible to make conditions in the Flow Builder using the value of inputs labeled with Fruit. It works just as if the markup had used an <input> like this:

<label>Fruit</label>
<div class="combo-box">
  <input type="text" value="Banana" />
  <div class="combo-box-trigger">..icon..</div>
</div>

Example of using the getValue function:

userflow.registerCustomInput('.combo-box', (el) => {
  const valueEl = el.querySelector('.combo-box-value')
  return (valueEl && valueEl.textContent) || ''
})

In this case, Userflow will return Banana as the value, and leave out the ..icon.. part.

Teaches Userflow.js to treat HTML elements in your app as custom text inputs.

This is useful if, for example, you use combo boxes and want Userflow to treat them like regular <input> elements. Instead of reading a value property (as we do with input elements), the text content of the custom input element is used instead. Or, you can supply a custom getValue function to customize how to read a string value from an element.

Note that you can call this function multiple times to support multiple kinds of custom inputs.

Parameters

Parameter Description
cssSelector String, required - Valid CSS selector that matches your custom input element.
getValue Function, optional - If set, should be a function that takes an element and returns a string representing the custom input's current value. If not set, Userflow will default to using the text content of the whole element.

setCustomNavigate()

Example, where myRouter is a fictive router object:

userflow.setCustomNavigate((url) => myRouter.push(url))

Example with React Router app:

// File: history.js
import {createBrowserHistory} from 'history'

export default createBrowserHistory()

// File: index.js
import {Router} from 'react-router-dom'
import history from './history'
import App from './App'

ReactDOM.render(
  <Router history={history}>
    <App />
  </Router>,
  document.body
)

// File: wherever-you-load-userflow.js
import history from './history'

// ...
userflow.setCustomNavigate((url) => history.push(url))
// ...

By default, when performing Go to page actions, Userflow will cause full page loads using window.location.href = url.

Call this function to override this behavior.

This is useful for single page applications using in-app navigation through the window.history API.

Parameters

Parameter Description
customNavigate Function or null, required - A function taking a single string url parameter. Or null to turn off and use default behavior.

setInferenceAttributeFilter()

Example of ignoring all ids starting with auto-:

userflow.setInferenceAttributeFilters(
  'id',
  // Returns true if the id does not start with `auto-`
  (id) => !id.startsWith('auto-')
)

Example of using an array containing both a function and a regular expression:

userflow.setInferenceAttributeFilters('id', [
  // Ignore ids starting with `auto-`
  (id) => !id.startsWith('auto-'),
  // Only consider ids consisting of a-z and dashes
  /^[a-z-]+$/,
])

Restricts HTML element attribute values from being used for element inference.

By default, Userflow.js may use all values of attributes configured with userflow.setInferenceAttributeNames. The only exception is that, by default, ids ending in numbers will be ignored. This is to support some dynamic IDs out-of-the-box. The same logic is applied to data-id attributes.

Parameters

Parameter Description
attributeName String, required - The attribute name the filter should apply to. Example values: id, data-testid.
filters Function, RegExp instance, or an array of functions or RegExp instances, required - When Userflow considers an attribute value, it'll be passed through all the given filters before we decide to use it. Filter functions are called with the attribute value and must return a truthy value to allow Userflow.js to use it. Regular expressions must match the attribute value to allow Userflow.js to use it. You can pass a single function, a single regular expression, or an array with a mix.

setInferenceAttributeNames()

Example of overriding the list of attribute names to use:

userflow.setInferenceAttributeNames(['name', 'placeholder', 'data-testid'])

Tells Userflow.js which HTML element attributes may be used for element inference.

By default, Userflow.js may use the values of the following element attributes for inference:

Parameters

Parameter Description
attributeNames Array of strings, required - Names of HTML attributes that Userflow may use for element inference.

setInferenceClassNameFilter()

Example of ignoring dynamic class names starting with css-:

userflow.setInferenceClassNameFilter(
  // Returns true if the class name does not start with `css-`
  (cls) => !cls.startsWith('css-')
)

Restricts CSS class names from being used for element inference.

By default, Userflow.js may use all class names.

Parameters

Parameter Description
filters Function, RegExp instance, or an array of functions or RegExp instances, required - When Userflow considers a class name, it'll be passed through all the given filters before we decide to use it. Filter functions are called with the class name and must return a truthy value to allow Userflow.js to use it. Regular expressions must match the class name to allow Userflow.js to use it. You can pass a single function, a single regular expression, or an array with a mix.

setScrollPadding()

Example, if you have a 50px tall sticky header:

userflow.setScrollPadding({top: 50})

Example, if you have a 50px tall sticky header and a 20px tall sticky footer:

userflow.setScrollPadding({top: 50, bottom: 20})

To turn off again:

userflow.setScrollPadding(null)

By default, when Userflow needs to scroll an element (e.g. the target of a tooltip) into view, we use the built-in Element.prototype.scrollIntoView method. This doesn't work well with sticky header/footers, since the element may be scrolled within the browser's viewport, but still be below the sticky header/footer.

To get around this, you can instruct Userflow to scroll just a little further in any direction in order to get the element inside the viewport and away from the sticky header/footer.

Note that this behavior will not work, and we'll fall back to plain Element.prototype.scrollIntoView, if the target element is nested within other scroll containers.

Parameters

Parameter Description
scrollPadding Object or null - Set to an object to use scroll padding. Set to null to turn off again.
scrollPadding.top Number, optional - Padding from the top of the viewport (pixels)
scrollPadding.right Number, optional - Padding from the right of the viewport (pixels)
scrollPadding.bottom Number, optional - Padding from the bottom of the viewport (pixels)
scrollPadding.left Number, optional - Padding from the left of the viewport (pixels)

Client-side events

These are events that you can subscribe to via userflow.on().

Note that these events are not related to the events you track with userflow.track.

checklistEnded

Store in own database when a specific checklist is closed:

userflow.on('checklistEnded', (event) => {
  if (event.checklist.id === '52e7e20d-f351-4528-9400-95de7b4ff6be') {
    myDb.update({getStartedChecklistClosed: true})
  }
})

Emitted when a checklist is permanently closed/dismissed. This typically happens when the user clicks "Dismiss checklist".

Event properties

When the event is emitted, listeners receive a single object argument with the following keys:

Key Description
checklist Content object - Checklist that ended.

flowEnded

Emitted when the flow is permanently closed. This typically happens due to a user action, such as by clicking the X or clicking a button with a "Close" action.

Event properties

When the event is emitted, listeners receive a single object argument with the following keys:

Key Description
flow Content object - Flow that ended.

Object interfaces

This section contains definitions of objects used in various methods and events.

Content object

Represents a content item (flow/checklist).

Properties

Key Description
id String
type String - Indicates the type of content. One of: checklist, flow