Installing Chameleon

Getting Chameleon installed, the four minute guide

Chameleon works using JavaScript - you install a couple lines of code on your site / web app and this allows you to see the Editor and for your users to see tours, when published. There are two simple steps required to get started:

Adding the Chameleon code snippet

Installing via Segment

Note: only applies if Segment installed on all pages where you intend to display tours.

If you use Segment then you can automatically install the Chameleon snippet using the "Enable with Segment" button (see image below). This will also send product data (events and user properties) you are tracking with Segment to Chameleon, to use for segmentation and conversion.

To connect and Chameleon please follow the steps below:

  1. Login to Chameleon
  2. In the Setup page, hit "Install now" and then "Enable with Segment"
  3. Go through the Segment authorization flow (couple clicks)
  4. Use to connect to third party apps.

Highfives — That's it, you're connected and the Chameleon Editor will now be available on the properties that is implemented.

Installing via Google Tag Manager

You can use a snippet manager such as Google Tag Manager (GTM). To do this, follow these steps:

1. Create new tag and add the Chameleon code snippet

  1. Name your tag: Chameleon
  2. Select Custom HTML
  3. Paste your code snippet (found in your dashboard)
  4. Select All Pages for the trigger

2. Identify users and send any user property via Variables. For each user property:

  1. Create a New User-Defined Variable
  2. Select Custom JavaScript

  3. Copy and paste the following, and include the relevant variable

        function() {
          var uid = window.uid; //<REPLACE WITH USERID PROPERTY>;
          return uid;

    1. Name the property by adding UID (in this case) in the Global Variable Name and Rename Variable fields

Ensure all data sent as variables

All data sent to Chameleon needs to be defined in these variables and interpolated into the snippet. In order to work correctly these properties need to exist on the page so GTM can reference them. (email, created_at, any segment info, etc).

3. Publish the tag

Installing manually

If you don't use Segment or GTM then you can install the code manually. This only takes a few minutes, and is similar to installing other JS snippets, such as for analytics or A/B testing tools.

There are TWO PARTS to it:

1. script -- The basic Chameleon snippet (with your unique token) that installs the Editor and allows you to create and publish tours

<script type="text/javascript">/* Chameleon - better user onboarding */!function(t,n,o){var a="chmln",c="setup identify alias track set show on off custom help _data".split(" ");n[a]||(n[a]={}),n[a].accountToken=o,n[a].location=n.location.href.toString();for(var e=0;e<c.length;e++)!function(){var t=n[a][c[e]+"_a"]=[];n[a][c[e]]=function(){t.push(arguments)}}();var s=t.createElement("script");s.src=""+o+"/messo.min.js",s.async=!0,t.head.appendChild(s)}(document,window,"TOKEN");

2. chmln.identify -- Information about users that is required for showing tours, URL matching, targeting specific audiences and personalization

// This is an example script, don't forget to change the PLACEHOLDERS.
// Please confirm the user properties to be sent with your project owner.
chmln.identify(USER.ID_IN_DB, {     // Unique ID of each user in your database (e.g. 23443 or "590b80e5f433ea81b96c9bf6")
  email: USER.EMAIL,                // Put quotes around text strings (e.g. "")
  created: USER.SIGN_UP_DATE,       // Send dates in ISO or unix timestamp format (e.g. "2017-07-01T03:21:10Z" or 1431432000)
  name: USER.NAME,                  // We will parse this to extra first and last names (e.g. "James Doe")
  role: USER.ROLE,                  // Send properties useful for targeting types of users (e.g. "Admin")
  logins: USER.LOGIN_COUNT,         // Send any data about user engagement (e.g. 39)
  project: USER.PROJECT_ID,         // Send any unique data for a user that might appear in any page URLs (e.g. 09876 or "12a34b56")

  company: {                        // For B2B products, send company / account information here
    uid: COMPANY.ID_IN_DB,          // Unique ID of the company / account in your database (e.g. 9832 or "590b80e5f433ea81b96c9bf7")
    created: COMPANY.SIGN_UP_DATE,  // To enable targeting all users based on this company property
    name: COMPANY.NAME,             // Send any data that appears within URLs, such as subdomains (e.g. "airbnb")
    trial_ends: COMPANY.TRIAL_ENDS, // Send data about key milestones (e.g. "2017-08-01T03:21:10Z")
    version: COMPANY.VERSION,       // If your software varies by version then this will help show the correct guidance (e.g. "1.56")
    plan: COMPANY.PLAN,             // Send null when no value exists (e.g. "Gold", "Advanced")
    spend: COMPANY.CLV              // Send other properties that will help in targeting users (e.g. sales rep, source, stage)

Things to note

  • Make sure the snippet is included on all private pages - typically before </head>
  • Use the snippet found in your dashboard, because it contains your personalized
  • Ensure you replace USER.ID_IN_DB and the other PLACEHOLDERS with the variables your codebase uses for user IDs / records and the other data.
  • You can install this on any subdomain (or locally), although we recommend installing directly on production. Learn more here

The code snippet is available from your dashboard, from where you can also invite a developer to help.

Installing Chameleon on different environments

Installing locally

Implementation environment

We recommend implementing the snippet directly on your production environment. Users will not notice this - no tours are published without explicit action from you. Doing so will save you time and energy - it will avoid dealing with differences between your development and live environments when you would later make the switch.

You can load the Chameleon Editor on your local computer if you would like to first test locally before deploying to production. To do this: add the snippet locally or to a test/staging environment, then simply reload the page.

Please feel free to contact us if you have any further questions or suggestions.

A note about authentication

To keep you authenticated (to identify you as an admin and show the Chameleon Editor) we store your authentication information in an encrypted, HttpOnly, secure cookie that is and only served to us over a secure connection (https).

Using Chameleon on multiple sites

You can use the same snippet on all three sites, and launch the Sidebar on the different sites by going via and entering the different URL before hitting Launch Sidebar. This will authenticate you as an administrator on those sites and show you the Editor.

This also means that in the Sidebar you will see all the tours you are using across the sites. Anyone authorized as an admin (you can invite others at will be able to edit any of these tours. If you want separation then you'll need to sign up with the separate email addresses on our site and you will essentially have different logins and accounts.

To make sure the tours show on the correct sites, you can use the URL matching for each step. To learn more about this, see URL matching.

Selectively hiding Chameleon

We split Chameleon into two parts, what your end users see (user) and what you and your team see (admins). You can hide/suppress Chameleon for each of those two groups by picking one of A, B or C below.

The use case for this: When your app and homepage are on the same subdomain and you have no other way to limit tours based on the url of the page.

When integrated directly: include this on the line after the Snippet When integrated via Segment add window.chmln || (window.chmln = {}); before one of the options in the code below

    // A. To hide Chameleon for your end users

    chmln.elusive = 'user';

    // B. To hide Chameleon from you and your team (to treat yourself as an end user)

    chmln.elusive = 'admin';

    // C. To hide Chameleon from everyone (as if it was not installed)

    chmln.elusive = 'user,admin';

Showing Chameleon on multiple domains

As long as your plan allows it, you can show any tour you build on any domain where you've installed your Chameleon snippet.

If you have tour steps that only show on a specific URL, you'll need to use URL matching, to make sure that the step will show on the different domains. For instance if the URL you build your tour on is '', you'll want to use wildcards depending on how the domain can change.

  • If the subdomain changes, you might match your tour-step to "http://*"
  • If the path changes, you might match your tour-step to "*"
  • If you allow your users to install your app on their domain, you may want to match your step to the path of your app, using "*/user/settings/". If matching to the path won't work, take a look at User variables to include your user's domain, or the hostname of the page they're working on.

If you use a page User Action to redirect tours to a different page, you'll also need to update the URL you use to transition-to that page. To do this, you'll want to use User variables within the User Action to make sure the page is the correct location.

Single Page Apps

Chameleon works with single-page web applications and across all frameworks, such as Angular, React, Ember etc. and can anticipate URL changes or content changes in order to show tours.

When installing the Chameleon snippet on your Single Page App just make sure chmln.identify is called when your app learns what user is on the page (likely because the user logs in or refreshes the page). If the content of your Single Page App changes but no page-refresh or log-in/log-out happens, then chmln.identify does not need to be called again.

The chmln namespace is found within the window scope, and can be accessed at window.chmln in scoped frameworks.

Launching the editing Sidebar

Once a page is loaded where your snippet is installed, that domain will show up in your dashboard. From there you can click 'Visit' to launch the Editor Sidebar on your site. This will identify you as an administrator so you see the Editor.

Enabling advanced segmentation

You can show variations of tours to different user groups. You can create these groups (segments) using any data you already collect about a user. This helps you create more personalized UX which should lead to higher engagement and conversion.

If you have setup Chameleon using Segment then you are automatically sending user data to Chameleon, and you can automatically use this in the Editor. If you setup manually, then you will need to send user data manually.

Sending additional user properties

As part of the Chameleon snippet, you already identify users with a unique ID:


You can simply send additional pieces of data about that user in this statement. At minimum, we recommend sending: created date and email, but you should send whatever you would like to use to differentiate users (e.g. role, plan, source, spend etc.)

An example of how you would alter the above JavaScript follows:

chmln.identify(, {name:, email:, created:currentUser.createdAt });

We also track some basic properties that you can use, such as: platform, device, screen, browser, IP address, locale, city, state, country, timezone, and language.

Seeing existing user properties

To see all the user properties currently being sent, you can run some code in your local browser. \n\nOpen the JavaScript console, under Developer Tools (or hitting CMD + ALT + J for Chrome on Mac) and paste the following code and hit Enter:{kind: 'profile', source: 'chmln'}).map(function(p) { return p.get('prop') })

Here are some more examples of what you might send. More available on our Github

<script type="text/javascript">
  // Add the snippet here with account id (i.e. '<%= ENV['CHAMELEON_ACCOUNT_TOKEN'] %>')
  // Assuming you have exposed `helper_method :current_user` in your `ApplicationController`
  <% if current_user.present? %>
          uid: '<%= %>',
          created: '<%= current_user.created_at.iso8601 %>',
          email: '<%= %>',
          plan: '<%= current_user.account.plan_name %>',
          spend: '<%= current_user.account.plan_cost %>'
  <% end %>
// Add the snippet here with account id (i.e. config.chameleonAccountId)
// Assuming you preload your page with a current user

(function() {
  if( {
      created: currentUser.createdAt,
      plan: currentUser.planName,
      spend: currentUser.planCost
// Add the snippet here with account id (i.e. config.chameleonAccountId)
// Assuming you call `currentUserLoaded` after fetching the user

(function() {
  var currentUserLoaded = function(currentUser) {
      created: currentUser.createdAt,
      plan: currentUser.planName,
      spend: currentUser.planCost

  var xhr = $.get('/user.json');
  xhr.done(function(data) {
    // Setup other aspects of the environment

<script type="text/javascript">
  // Add the snippet here with account id (i.e. <?php echo $GLOBALS['chameleonAccountId'] ?>)
  // Assuming your page has loaded the current user as the object $current_user
  <?php if (var_dump((bool) $current_user->present)): ?>
      uid: '<?php echo $current_user->id ?>',
      created: '<?php echo $current_user->created_at ?>',
      email: '<?php echo $current_user->email ?>',
      plan: '<?php echo $current_user->account->plan_name ?>',
      spend: '<?php echo $current_user->account->plan_cost ?>'
  <?php endif; ?>


Chameleon will interpret a property as a timestamp for a few reasons:\n\n1. If the timestamp is ISO 8601 standard, Chameleon will always assume the value is a timestamp.\n2. If the timestamp is a Unix Timestamp that falls between 1973 and 2033 and the name is either 'created', or ends in '_at' or '_time'. \n\nChameleon will interpret any of these properties as a timestamps: {started: \"2016-09-05T15:45:39+00:00\", ended: \"2016-09-05T15:45:39Z\", created: 1472985601, started_at: 1095292800, ended_at: 1095352800}.

Reserved Keywords

Chameleon has some reserved keywords that are not passable in identify. They include: id, user, platform, device, screen, browser, IP address, locale, city, state, country, timezone, and language.

Sending user actions

You can also segment based on which actions a user takes inside your product. You can send these events through our API. Read Create Events for more information.