slack-google-analytics

I recently stumbled upon Nico Miceli‘s post on sending Slack data to Google Analytics, so I decided to take a look at how I could use this app to analyze Slack activity.

We have multiple Slack teams with multiple channels where I work, and it has really helped us collaborate on all levels. We mostly use it for knowledge and article sharing. I’m going to use Nico’s app with a couple customizations to do the following:

  • Understand user activity broken down by team and channel
  • Curate all links (URLs) posted in each of the channels
  • Understand general keyword usage to see what people are talking about

App updates to pull team_id and URL

I’m going to assume you’ve already went through the steps to deploy your app in Heroku as outlined in Nico’s article. Next, we’ll want to add a little additional code to pull the team_id and URLs. This will allow us to achieve our first 2 requirements outlined above.

First, we’ll want to add a new custom dimension in Google Analytics to store the team_id and URL. Screen Shot 2015-11-15 at 3.46.02 PM

Next, we’ll add a couple lines of code to grab the team_id from slack as shown below.Screen Shot 2015-11-15 at 3.30.41 PM

Then we’ll add a line of code to parse out a URL from a post. Since URLs are returned within ‘<URL>’, we can just look inside the msgText and grab it from inside those characters.
Screen Shot 2015-11-25 at 4.48.26 PM

Lastly, we’ll add this to our data variable, so that it gets added to our hit. This will pass the team_id to the custom dimension we created in Google Analytics. Make sure to change the custom dimension ID if it’s not number 4 and 5 as shown in this example.
Screen Shot 2015-11-25 at 4.49.30 PM

The final code should look like this:

 //Set up Reqs
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var qs = require('querystring');

//set up heroku environment variables
var env_var = {
 ga_key: process.env.GOOGLE_ANALYTICS_UAID
};

//Server Details
var app = express();
var port = process.env.PORT || 3000;

//Set Body Parser
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));


//Routes
app.get('/', function(req, res){
 res.send('here');
});

app.post('/collect', function(req, res){

 var channel = {
 id: req.body.channel_id,
 name: req.body.channel_name
 };
 var user = {
 id: req.body.user_id
 };
 var team = {
 id: req.body.team_id
 };
 var msgText = req.body.text;
 var teamDomain = req.body.team_domain;


 function searchM(regex){
 var searchStr = msgText.match(regex);
 if(searchStr != null){
 return searchStr.length;
 }
 return 0;
 };

 function searchS(regex){
 var searchStr = msgText.split(regex);
 if(searchStr != undefined){
 return searchStr.length;
 }
 return 0;
 };

 var url = msgText.substring(msgText.lastIndexOf("<http")+1,msgText.lastIndexOf(">"));
 var url_dimension = "http" + url;
 var wordCount = searchS(/\s+\b/);
 var emojiCount = searchM(/:[a-z_0-9]*:/g);
 var exclaCount = searchM(/!/g);
 var questionMark = searchM(/\?/g);
 var elipseCount = searchM(/\.\.\./g);

 //Structure Data
 var data = {
 v: 1,
 tid: env_var.ga_key,
 cid: user.id,
 ds: "slack", //data source
 cs: "slack", // campaign source
 cd1: user.id,
 cd2: channel.name,
 cd3: msgText,
 cd4: team.id,
 cd5: url_dimension,
 cm1: wordCount,
 cm2: emojiCount,
 cm3: exclaCount,
 cm4: questionMark, //need to set up in GA
 cm5: elipseCount, 
 dh: teamDomain+".slack.com",
 dp: "/"+channel.name,
 dt: "Slack Channel: "+channel.name,
 t: "event",
 ec: "slack: "+ channel.name + "|" + channel.id,
 ea: "post by " + user.id,
 el: msgText,
 ev: 1 
 };
 console.log(JSON.stringify(data));
 console.log(req.body);
 //Make Post Request 
 request.post("https://www.google-analytics.com/collect?" + qs.stringify(data), 
 function(error, resp, body){
 console.log(error);
 })
 res.send("OK")
});

//Start Server
app.listen(port, function () {
 console.log('Listening on port ' + port); 
});<span style="line-height: 1.42857;">


As mentioned in Nico’s article you can check the app console logs to see if the variables are getting passed through correctly by typing in the following:

heroku logs -t

Create the reports for reporting and analysis

Now that we have our data flowing into GA, let’s create the reports.

Create advanced segments

First, I’m going to create segments for each of my teams. This will allow me to analyze the data broken down by each team in Slack. To retrieve your team id, go to here, and test the method. If you haven’t already, you’ll need to generate a token.
Screen Shot 2015-11-15 at 4.31.45 PM

Copy and past that ID into a new advanced segment and name it the title of your team.
Screen Shot 2015-11-15 at 4.24.50 PM

Repeat these steps for each of your teams.

Create custom reports for each channel

Now that I’m able to segment my data by team, I’m going to create a custom report for each channel. In GA, go to Customization and create a new report. Add the metrics and dimensions as shown in the screenshot below. This will allow us to analyze the data within this channel by user as defined in our requirements.
Screen Shot 2015-11-15 at 4.42.14 PM

Note, the filter name should match the channel name. Repeat this step for each of your channels. You could perform this step using advanced segments, but because all of my teams have a general channel, I created the custom report instead. If I went the advanced segment route, then I would need to create a unique segment for each team/channel combination.

Create a custom report that curates all URLs

Next, I want to curate all URLs and understand which user posted it. In order to do that, I’m going to create a new custom report with the slack user and URL dimensions as shown below.
Screen Shot 2015-11-15 at 4.56.48 PM

The final product should look something like this:
Screen Shot 2015-11-15 at 4.58.44 PM

Map the user IDs to their names

Now that our reports are all set up, you might be wondering who’s who for the slack user id. A quick way of looking at this is by running a test query at https://api.slack.com/methods/users.list/test. You could also export this to Excel and map the ID to the user’s name using a VLOOKUP. I’m going to use Google Sheets instead because it’ll automate the process.

Go into Google Sheets and create the following tabs below. I’m going to assume you already have the Google Analytics add on installed. If you don’t or have never used the Google Analytics addon with Google Sheets, you can read more about it here.

Report configuration
Create a report that pulls in total events, the URL and user id. Generate the report and you should be able to see the data in a new sheet.
Screen Shot 2015-11-15 at 5.39.57 PM
Screen Shot 2015-11-15 at 5.41.40 PM

Users
Create a new tab and title it Users. In this tab, we’ll need to map our user IDs to their names using the data from Slack. You can follow Nico’s tip by pulling the data out of Slack. If you have hundreds (or thousands) of users, then there are some other quicker technical ways of getting this data, but I won’t go into that in this article. For now, I’ll just pull my user id and make up a couple to ensure the formula in Google Sheets is working properly.
Screen Shot 2015-11-15 at 5.44.28 PM

URLs w/ Usernames
Create another tab that will map the user IDs to the names. This is where you’ll need to write a VLOOKUP to reference your users table from above.
Screen Shot 2015-11-15 at 5.45.38 PM

 

And that’s it! There are quite a few ways of going about the reporting aspect, but this is just one way of doing it. I particularly like this approach because everything is practically automated for you once your reports are set up in GA and Google Sheets. You won’t need to spend much time tooling around in GA or Excel to get the data you need for analysis.

Thanks to Nico Miceli and Joe Zeoli for writing the app. It’s a very creative and useful way to integrate Google Analytics with Slack.

 

One comment on “Customizing and Setting Up Reports Using Slackalytics

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.