Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

๐Ÿงฎ sheets โ‡” mixpanel

connect your google sheet with mixpanel! no coding required!

Install Now! See sample data here

๐Ÿ‘” tldr;

after installing you will see the sheets โ‡” mixpanel dropdown under extensions in any google sheet. this module provides two modes, which are exposed in the main menu:

each UI has a simple user interface, and is essentially a form you fill out that contains the necessary details to carry out your desired result.

๐Ÿฟ demo

youtube demo

๐Ÿ—บ๏ธ mappings (sheet โ†’ mixpanel)

sheet โ†’ mixpanel queries your currently active sheet to get your sheet's column headers.

once you choose the type of data you are importing, you will use the visual mapper to connect the column headers from your sheet to the required fields for the type of mixpanel data you are importing:

as a brief summary of the documentation mixpanel's data model for events requires fields for:

  • event name : what to call each event in mixpanel
  • distinct_id : the unique user identifier to whom the event is attributed
  • time : a valid date or time; if the sheet recognizes your chosen column as a 'date' or time', it should work as intended
  • insert_id : a value used to deduplicate records (optional)

all other columns in your spreadsheet will get sent as properties (event, user, or group)

you'll also need to provide :

note: since v1.12 syncs are not supported for events.

next, read about runs + syncs

๐Ÿ’ฝ exports (mixpanel โ†’ sheet)

mixpanel โ†’ sheet queries your mixpanel project for a report or cohort and makes the results available in a new sheet.

note that this will be identical to the functionality would get when exporting a CSV file from the mixpanel UI:

there are a number of parameters needed to fetch a CSV from mixpanel; the simplest way to gather those parameters is to paste the URL of the report/cohort you wish to sync from your mixpanel project, and the app should find them:

in case the URL does not contain all the values you need, the UI requires:

you can manually type these values in after pasting in a URL.

note: as of v1.12 insights, funnels, & retention are the only supported reports

next, read about runs + syncs

๐Ÿ”„ runs + syncs

each UI has a similar user interface for you to input your details with four key actions at the bottom:

  • Run: run the current configuration once; results are display in the UI
  • Sync: run the current configuration every hour; run receipts are stored in a log sheet
  • Save: store the current configuration
  • Clear: delete this sheet's sync and reload the UI

you may only have one sync active per sheet at a time.

if you are planning to sync data from your sheet to mixpanel, it is recommended that you do a "run" first.

once created, syncs will run on an hourly schedule; they can also be manually triggered from the main menu by choosing Sync Now!:

note: since v1.12 syncs are not supported for events.

๐Ÿ‘จโ€๐Ÿ”ง๏ธ development

local development

For local development, you will need to do the following:

  • clone the repo: git clone

  • install dev dependencies: npm install

  • install clasp globally: npm i g clasp

  • create a google sheet by importing the provided test data

  • in the google sheets UI, go to Extensions โ†’ AppsScript โ†’ Project Settings to get your scriptId:

  • using the scriptId create a .clasp.json file of the form:
	"scriptId": "your-googleApps-script-id",
	"rootDir": "/path/to/this",
	"projectId": "your-gcp-project"
  • run clasp login to create a .clasprc.json file of the form:
	"token": {
		"access_token": "",
		"scope": "",
		"token_type": "",
		"id_token": "",
		"expiry_date": ,
		"refresh_token": ""
	"oauth2ClientSettings": {
		"clientId": "",
		"clientSecret": "",
		"redirectUri": "http://localhost"
	"isLocalCreds": true

see these docs for more info


  • use npm run push to push the module's code into your instance

  • see package.json for other scripts; anything with a watch prefix will re-run on local code changes

code overview

Here's an overview of the code in the repo:

โ”œโ”€โ”€ Code.js				# routes + templates
โ”œโ”€โ”€			# this file
โ”œโ”€โ”€ appsscript.json		# extension manifest
โ”œโ”€โ”€ components			# data in/out logic
โ”‚ย ย  โ”œโ”€โ”€ dataExport.js
โ”‚ย ย  โ””โ”€โ”€ dataImport.js
โ”œโ”€โ”€ creds.json			# server-side credentials
โ”œโ”€โ”€ env-sample.js		# where test credentials go
โ”œโ”€โ”€ env.js
โ”œโ”€โ”€ jsconfig.json		# typescript config
โ”œโ”€โ”€ models				# models for data import
โ”‚ย ย  โ”œโ”€โ”€ modelEvents.js
โ”‚ย ย  โ”œโ”€โ”€ modelGroups.js
โ”‚ย ย  โ”œโ”€โ”€ modelTables.js
โ”‚ย ย  โ””โ”€โ”€ modelUsers.js
โ”œโ”€โ”€ package-lock.json
โ”œโ”€โ”€ package.json		# scripts + dependencies
โ”œโ”€โ”€ testData			# test data
โ”‚ย ย  โ”œโ”€โ”€ events.csv
โ”‚ย ย  โ”œโ”€โ”€ full\ sandbox.xlsx 	# (use this one)
โ”‚ย ย  โ”œโ”€โ”€ groups.csv
โ”‚ย ย  โ”œโ”€โ”€ tables.csv
โ”‚ย ย  โ””โ”€โ”€ users.csv
โ”œโ”€โ”€ tests				# local + server tests
โ”‚ย ย  โ”œโ”€โ”€ MockData.js
โ”‚ย ย  โ”œโ”€โ”€ UnitTestingApp.js
โ”‚ย ย  โ””โ”€โ”€ all.test.js
โ”œโ”€โ”€ types				# jsdoc + typescript types
โ”‚ย ย  โ”œโ”€โ”€ Types.d.ts
โ”‚ย ย  โ””โ”€โ”€ Types.js
โ”œโ”€โ”€ ui					# user interface
โ”‚ย ย  โ”œโ”€โ”€ mixpanel-to-sheet.html
โ”‚ย ย  โ””โ”€โ”€ sheet-to-mixpanel.html
โ””โ”€โ”€ utilities			
    โ”œโ”€โ”€ REPL.js			# a "quick and dirty" REPL for GAS
    โ”œโ”€โ”€ flush.js		# sending data to mixpanel
    โ”œโ”€โ”€ md5.js			# for $insert_id construction
    โ”œโ”€โ”€ misc.js			# various utilities
    โ”œโ”€โ”€ sheet.js		# for manipulating sheets
    โ”œโ”€โ”€ storage.js		# modifying storage configuration
    โ”œโ”€โ”€ toJson.js		# turn CSV to JSON
    โ”œโ”€โ”€ tracker.js		# usage tracking
    โ””โ”€โ”€ validate.js		# validation utils


you can run local tests with the watch-test-local script:

npm run watch-test-local

you can run server-side tests with the test-server script:

npm run test-server

in order for server-side tests to work, you will need to fill out params in a env.js file... there is a sample (env-sample.js) committed to the repo; this is what passing server-side tests look like (in the GCP console):

๐Ÿ“ limited use policy

Sheetsโ„ข โ‡” Mixpanel use and transfer to any other app of information received from Google APIs will adhere to Google API Services User Data Policy, including the Limited Use requirements.

The app is free to use and does not contain ads, nor will any data collected by Sheetsโ„ข โ‡” Mixpanel be resold in any way. No human can read your spreadsheets; usage data is collected and anonymized only to improve the end-user's experience.

๐Ÿ” permissions

Using the principle of least-privilege, Sheetsโ„ข โ‡” Mixpanel requests access to three sensitive scopes to support application functionality, which are explained below:

  • is used to draw a dynamic UI which maps the columns headers of your currently active Google Sheetโ„ข into dropdowns in the extension interface.

  • is used to support scheduled hourly "sync" functionality so the pipeline you've configured in the UI can run automatically.

  • is used to send your mapped data to mixpanel and to request your report/cohort data from mixpanel.

no other sensitive scopes are requested by the application.

๐Ÿ’ฌ motivation

google sheets are databases. mixpanel is a database. it should be easy to make these things interoperable. now it is!

that's it for now. have fun!


๐Ÿ”„ integrate mixpanel with google sheets






No releases published


No packages published