In this article I’ll share with you a cool project some of our cumulians have developed. By the end of it, we achieve a multi-tenant analytics platform where the user not only sees only data relevant to them, but also gets greeted with a theme that is meant for them too. Most importantly, all of this is achieved by a simple trick with the use of Cumul.io tags and Auth0. There are a few features that this project highlights:
In the end we get an application that uses template dashboards that were set up in Cumul.io. But, we use them in a multi-tenant application, meaning they can be used by more than one user. To achieve this, we apply filters and styles based on the user that logged in.
Notice below that when Brad logs in, he has access to 3 dashboards. He also has a certain theme to his dashboards and is seeing everything in English.
Whereas Angelina has access to only 2 dashboards and she is initially seeing everything in French. She also has a different colour scheme.
On top of this, we are also displaying drill-through dashboards for both of them on their Marketing/Commercialization dashboard:
The whole article can be seen as a continuation of the Multi-Tenancy on Cumul.io Dashboards with Auth0 article. If you haven’t already, I recommend you have a quick read through. This article went through how to set up users with Auth0, and use user information to filter the dashboard. The initial setup here is much the same, but we will be adding some extra data about/for the user in Auth0.
First we will walk through how we set up our demo dashboards. For the purposes of this walk through we have created mock data that we’ve also made public. Then, we will walk through how we set up our Auth0 application and users.
As a final step, we will also briefly walk through some key parts of the application code. This will range from loading dashboards to listening to custom events.
As always, you can access the public repo to replicate the project entirely if you so wish 🙂 . To do so, clone cumul.io-multitenancy-auth0-example. The Readme includes detailed instructions to run the project!
Let’s run through how to set this whole thing up:
For the purposes of this demo we have created our own set of dashboards. However, you are free to create as many dashboards as you like. The code we write in the next sections will allow for you to flexibly add or remove dashboards. But let’s have a look at the ones we have created;
Overall, we will have 3 main dashboards: Marketing, Sales and Leads. And additionally, we also have a drill through dashboard called ‘Marketing Drillthrough’. This one will be shown when a custom event is triggered from the Marketing dashboard.
If you would like to create similar dashboards, you can use our mock data that we’ve made public below. We’ve also made the dashboards public if you would like to use them, but make sure to duplicate them and make copies of them on your Cumul.io account:
Once you have your dashboards ready, we want to give them tags. Later, we will use these tags in our app to get the dashboards we want to use and embed. This will allow us to set up a system that only provides a tag and gets dashboards without having to know all of their individual ids. It also allows you to easily add/replace dashboards in your app by just adding/removing tags in Cumul.io.
Adding tags to dashboards is very simple. Here, due to lack of imagination, we are going to give the tag auth0-mt to all of our main dashboards (Marketing, Sales and Leads). Of course, you are free to give whatever tag you find more appropriate!
Finally, we are going to give some tags to our drill-through dashboard. We have here again a tag to describe a drill-through dashboard, auth0-mt-dt, but we are also adding 2 extra tags:
These tags start with a ce- and are used as a way for this application to know what custom event should drill through to this dashboard. It is set up so that it looks like this:
Similar to the custom event tag, we are also adding a parameter tag. This will be used in our application in the case where a custom event is used to fill in some parameters. The tag also provides information on what type the parameter is and what custom event needs it. It is set up in the following way:
We will add one custom event and one parameter tag to our drill through dashboard:
Note: Make sure that your custom event name, parameter type or parameter name do not have a ‘-‘ in them. We use this character to decode the information in the tags. If you are interested in how this works, you can have a look at getExtraTags() in dashboardClient.js
Finally, this is what our tags for the drill-through dashboard will look like:
One last thing to do on the dashboards is setting up custom events and parameters. In our scenario we display a drill through dashboard when a campaign is selected in the Marketing dashboard. We simply go to the settings of this chart and in ‘Interactivity’ we turn on Custom Events:
Notice the name of the custom event is the same as the one that was provided in the tags for the drill through dashboard. We will later set up our application so that when this custom event is triggered, we know to display the correct dashboard by checking it’s ce- tag.
We then set up our Marketing drill-through dashboard. Here, we set the parameters on which we want to filter the dashboard on. We set 2 parameters, campaignName and companyId. The first will be used with the custom event that selects the campaign to drill through on. The second will be used to filter all dashboards so that the user only sees data relevant to their companyId. We will set the companyId for a user in Auth0 in the following step. In the dashboard editor, we go to the Filters and add the following Parameters and Dashboard Filters.:
For all of the other dashboards we only set the companyId parameter and use it in a dashboard filter.:
The first thing you need for this step is an account with Auth0 which you can set up here. For this demo, we have set up 2 users, our trustee mascots, Angelina Julie and Brad Pots. We will use the Auth0 user management system to provide extra metadata about the user. These will include everything from custom themes to which dashboards they have access to.
This demo project is set up to use information provided in user_metada and app_metadata for each user to style and filter all of our template dashboards we set up in the previous section. In addition, we use the User Management in Auth0 to determine some access rights for each user too.
The following instructions are so that you can run the demo project yourself in case you want to:
For each user you create, add some properties to the user_metadata. Here are the ones used in our demo application :
This is what our user_metadata for Angelina and Brad look like:
Add the following properties to each users app_metadata:
This is what our app_metadata for Angelina and Brad look like:
user_metadata can be thought of as user preferences that could be easily changed by the users themselves. app_metadata on the other hand holds user information that only a admin would be able to control and edit.
Alright, so far we’ve seen the dashboards we will be using and we’ve created users in Auth0. Now let’s see how we use the information set in Auth0 in our application. In this section we will cover a few key steps that were implemented in the demo project so as to;
Seems like a lot, but we will only highlight some of the key parts of the project to simplify. By the end, you will have enough information to run and modify the project to your will! To follow these steps I recommend taking a look at the cumulio-multitenancy-auth0-example repo. We will refer to and summarize code snippets from this project! If you want to run the project yourself, the Readme also includes detailed instructions on how to do so.
The functions related to getting dashboards can all be found in <a href="https://github.com/TuanaCelik/cumul.io-multitenancy-auth0-example/blob/main/dashboardClient.js">dashboardClient.js</a> at the root of the project. To get dashboards, we need to make a request to the Cumul.io API specifying which dashboards we want. To do so, we have created 2 functions; getMainDashboards() and getDrillThroughDashboards(). Before anything else, we create our Cumul.io client with our Cumul.io API key and token (which you can find in your Cumul.io profile);
In this API call, we are getting all private dashboards. In the include property we set a where filter on the Tag resource (filtering to “auth0-mt”) and do an inner join. This means we only get the dashboards that have that Tag resource associated with them (the specific Tag resource itself is also returned by that API call).
In this API call however, we use the search property to get the dashboards that have the drill-through tag. We use this because the response also includes all other tags as well (like the custom event and parameter tags). We use the include property to include all other Tag resources associated with those dashboards (notice that there is no where or jointype property specified here). This allows us to get all drill-through dashboards together with all their other associated Tags.
In DashboardClient we map each of these dashboards we fetch in a dashboards data structure.
Where tabs map to all of the main dashboards and drill_throughs to all the drill through dashboards we received from the API calls above.
Let’s add the main dashboards to the tabs property:
And let’s also fill in the extra properties for drill through dashboards in the getExtraTags() function:
The getExtraTags() function creates the following object for each drill through dashboard by filtering and decoding it’s extra ce- and p- tags:
Once we have our dashboards, we want to make sure the logged in user only sees the dashboards that they are allowed to see. Not only that but we also want to make sure that they only see data that is relevant to them.
As a first step, we create a /dashboards end point in server.js. This checks a user’s properties and returns only those dashboards that the user is allowed to see. Let’s have a look at how we had defined a user’s dashboard access in Auth0. Here is Angelina’s app_metadata:
In server.js we will check the “scope” property and return dashboards whose names only match the ones there. To do so we create a getUserProperty() function:
We then use this function while fetching all of the user related dashboards and returning them in the /dashboards endpoint:
Note that if the dashboards property in Auth0 includes a “*” this code treats this as meaning that the user has access to all dashboards.
We fetch dashboards from the /dashboards endpoint in src/app.js and load them by adding the the following piece of code in a fetchAndLoadDashboards() function:
Finally, we will also like to filter the actual data that the user can see in the dashboards. For this we will use the parameter and filter we set up in Step 1. We create an /authorization end point and return a new authorization key and token in server.js. While doing so, we include elements from user_metadata and app_metadata. This allows Cumul.io to filter dashboards and set themes based on user authentication. Here are some of the key steps to accomplish this.
Notice here, we fill every key-value pair of the parameter property that belongs to a user in options.metadata. This is how we ensure that the companyId parameter that we set in the dashboards are filled with the value set in Auth0 for that user.
Similarly, we also fill in the custom themes and colours for the user by adding it to options before we create the authorization tokens. For more on this, have a look at the source code in server.js.
In this final step we will try to achieve the following:
In short, the user can select a certain data point in the bar chart, and we display a drill through dashboard that contains data relevant to the selection.
So that we display the correct dashboard based on a given event sent by the dashboard, we store custom event names and the dashboards they should load after fetching all the dashboards from server.js. To do so we add the following code into fetchAndLoadDashboards() in app.js:
Now, we can listen to events by calling Cumulio.onCustomEvent() and select the correct dashboard to embed. Not only that, but since we have to filter the drill through dashboard based on which element in the bar chart was clicked, we also have to create a new authorization token (similar to the previous section). This new authorization token will include values for the parameter we set in Step 1.
Note that based on what type of chart the event is triggered from, the value you want may come in a different property. Here, as we used a bar chart our value is stored in e.data.category.id.
This was quite an advanced use case of Cumul.io and its functionalities. But the advantages and flexibility it provides is undeniable. A combination of tags, custom events, authentication steps have allowed us to create a multi-tenant, highly customizable analytics platform. Another cool thing about this particular project I would like to highlight is how flexible it is to modifications. So if you would like to you only need to clone the repository, and once you follow the steps in the readme you can:
And that’s it! 🎉
Finally, here are some resources you might find helpful: