# How to Integrate Retool with Mixpanel

- Tool: Retool
- Difficulty: Intermediate
- Time required: 20 minutes
- Last updated: April 2026

## TL;DR

Connect Retool to Mixpanel by creating a REST API Resource pointing to Mixpanel's Query API (mixpanel.com/api/query) or JQL endpoint, authenticated with Basic Auth using your service account credentials. Pull event counts, funnel data, and user properties into Retool tables and charts, then join Mixpanel's product analytics with your internal user database for enriched operational dashboards.

## Why Connect Retool to Mixpanel?

Mixpanel is built for product analysts to explore user behavior interactively. But operations teams, customer success managers, and growth engineers often need Mixpanel data surfaced in operational contexts — alongside user records from the database, support ticket history from Zendesk, or subscription data from Stripe. Building a custom internal tool in Retool that combines Mixpanel's behavioral data with your operational data creates more actionable dashboards than either system provides alone.

Common scenarios include: a customer success panel that shows each account's product engagement metrics next to their subscription tier, letting CSMs identify at-risk accounts proactively; a user activity dashboard that shows which features a user has and hasn't used, informing onboarding interventions; or a funnel analysis board that lets the growth team query Mixpanel conversion rates for specific user cohorts while simultaneously viewing the cohort's attributes from the database.

Mixpanel's Query API provides programmatic access to events, funnels, retention, segmentation, and engagement data — the same analytical capabilities available in Mixpanel's web interface. The JQL endpoint adds flexibility for custom queries using Mixpanel's JavaScript-based query language, enabling the kind of ad-hoc analysis that doesn't map neatly to the standard endpoints. Both API styles work well through Retool's REST API Resource.

## Before you start

- A Retool account (Cloud or self-hosted) with permission to add Resources
- A Mixpanel account with at least Analyst access to the project you want to query
- A Mixpanel service account created in the project settings (Settings → Project Settings → Service Accounts) — service accounts are separate from personal user accounts and are the recommended authentication method for API access
- Your Mixpanel project token and project ID (found in Settings → Project Settings → Overview)
- Basic familiarity with Mixpanel's event data model: events, properties, distinct_id

## Step-by-step guide

### 1. Create a Mixpanel service account and gather credentials

Mixpanel uses service accounts for programmatic API access. Service accounts are separate from personal user accounts and can be scoped to specific projects, making them the correct authentication method for Retool integrations.

Log into Mixpanel and navigate to Settings (gear icon, top-right). Go to Project Settings → Service Accounts. Click Add Service Account. Enter a name like 'Retool Integration', select the access level (Analyst is sufficient for read-only dashboards), and specify which projects this account can access. Click Create.

Mixpanel shows you the service account's username (format: projectname.serviceaccount@serviceaccounts.mixpanel.com) and a generated secret password. Copy both immediately — the password is only shown once. The service account username and password are what you will use for Basic Auth in the Retool resource.

Also note your project's Project ID from Settings → Project Settings → Overview. The Project ID is a numeric identifier (not the project name or token) that appears in API URL paths and query parameters. For the Query API, you will also need the Project Token — this is different from the Project ID and is used in some request bodies.

For the Mixpanel Query API's base URL, you will use: https://mixpanel.com/api/query (for the standard endpoints) or https://mixpanel.com/api/2.0 (for older API versions). The JQL endpoint is: https://mixpanel.com/api/jql.

**Expected result:** You have a Mixpanel service account username (email format) and password, plus your project's Project ID. These are all the credentials needed to configure the Retool REST API Resource.

### 2. Create the Mixpanel REST API Resource in Retool

Open Retool and navigate to the Resources tab. Click Add Resource and select REST API from the list. Configure the resource:

- Name: 'Mixpanel Analytics'
- Base URL: https://mixpanel.com/api/query

For authentication, select Basic Auth from the Auth dropdown:
- Username: your service account's full email/username (e.g., myproject.retool@serviceaccounts.mixpanel.com)
- Password: the service account secret password

Add a default header for all requests:
- Key: Accept
- Value: application/json

Click Save Changes.

To verify the connection, create a test query in a Retool app using this resource:
- Method: GET
- Path: /events
- Add URL parameters: project_id: {{ YOUR_PROJECT_ID }}, from_date: {{ new Date(Date.now() - 7*24*60*60*1000).toISOString().split('T')[0] }}, to_date: {{ new Date().toISOString().split('T')[0] }}, event: ["page_view"] (replace with an actual event name from your Mixpanel project)

Click Run. If successful, you'll see a response object with date-keyed event count data. If you get a 400 error, verify the project_id parameter matches your numeric Mixpanel Project ID (not the project token or name).

**Expected result:** The Mixpanel REST API Resource appears in the Resources list. A test GET query to /events with valid project_id and date parameters returns event count data, confirming the Basic Auth credentials and resource configuration are correct.

### 3. Query event data and build a daily activity chart

With the resource configured, build your first analytics query. The Mixpanel Event Segmentation endpoint (/events/general) returns event counts broken down by day or hour, with optional property filters.

Create a new query using the Mixpanel resource:
- Method: GET
- Path: /events/general
- URL Parameters:
  - project_id: {{ YOUR_PROJECT_ID }} (your numeric project ID)
  - from_date: {{ dateRangePicker.startDate }} (reference a DateRangePicker component)
  - to_date: {{ dateRangePicker.endDate }}
  - event: {{ JSON.stringify([eventSelect.value]) }} (selected event from a dropdown)
  - unit: day
  - type: general

Mixpanel's response format has nested date keys: data.values returns an object where keys are event names and values are objects with date strings as keys and counts as values. You need a transformer to flatten this into an array suitable for Retool's Chart component.

Add a transformer that converts the nested Mixpanel response into an array of { date, count } objects for chart binding. Add a Chart component, set its type to Line, and bind it to the transformer's output. Set the X-axis to the date field and Y-axis to the count field.

```
// JavaScript transformer for Mixpanel event segmentation response
// Mixpanel returns nested objects: response.data.values.{eventName}.{date} = count
const response = data;
const eventData = response?.data?.values || {};

// Extract the first event's data (or handle multiple events)
const eventNames = Object.keys(eventData);
if (eventNames.length === 0) return [];

// Flatten into chart-ready array
const firstEvent = eventNames[0];
const dailyCounts = eventData[firstEvent] || {};

return Object.entries(dailyCounts)
  .map(([date, count]) => ({
    date: date,
    count: count,
    event: firstEvent
  }))
  .sort((a, b) => new Date(a.date) - new Date(b.date));

// For multiple events in one chart, use this pattern instead:
// return eventNames.flatMap(eventName =>
//   Object.entries(eventData[eventName] || {})
//     .map(([date, count]) => ({ date, count, event: eventName }))
// ).sort((a, b) => new Date(a.date) - new Date(b.date));
```

**Expected result:** A line chart shows daily event counts for the selected event over the chosen date range. Changing the date range picker updates the chart. The chart renders cleanly with one data point per day.

### 4. Query funnel conversion rates with the Funnels API

Mixpanel's Funnels endpoint returns conversion data for defined funnel sequences. You need to reference the funnel by its Mixpanel funnel ID, which you can find in the Mixpanel web app under the Funnels report URL (the numeric ID in the URL: /project/123/view/456/funnels/789).

Create a new query:
- Method: GET
- Path: /funnels
- URL Parameters:
  - project_id: {{ YOUR_PROJECT_ID }}
  - funnel_id: {{ funnelIdInput.value }} (or hard-code if using a specific funnel)
  - from_date: {{ dateRangePicker.startDate }}
  - to_date: {{ dateRangePicker.endDate }}
  - unit: week (options: day, week, month)

The funnel response has a nested structure: data contains an object with funnel analysis data, including step-by-step counts and conversion rates. Write a transformer to extract the step names, entry counts, and conversion rates.

Alternatively, for ad-hoc funnel definitions without a saved Mixpanel funnel, you can use JQL to define a funnel inline. Create a second query using the JQL endpoint (https://mixpanel.com/api/jql as the resource base URL, or add a second Mixpanel resource for JQL) — the JQL approach is more flexible but requires knowledge of Mixpanel's JQL syntax.

Bind the funnel data to a Table component showing each step, number of users who reached it, and the conversion rate. Add a Bar Chart showing conversion rates per step for visual comparison. For complex multi-funnel dashboards, RapidDev can help build reusable transformer functions that normalize Mixpanel's varied response formats across different API endpoints.

```
// JavaScript transformer for Mixpanel Funnels API response
// Extracts step-level conversion data from the funnel response
const response = data;

// The funnel response structure varies - inspect data.meta for step names
const stepNames = response?.meta?.dates || [];
const funnelData = response?.data || {};

// Handle the standard funnel response format
if (response?.data?.steps) {
  return response.data.steps.map((step, index) => ({
    step_number: index + 1,
    step_name: step.event || step.step_label || 'Step ' + (index + 1),
    count: step.count || 0,
    conversion_from_first: step.count && response.data.steps[0].count
      ? ((step.count / response.data.steps[0].count) * 100).toFixed(1) + '%'
      : '0%',
    conversion_from_prev: (index > 0 && step.count && response.data.steps[index-1].count)
      ? ((step.count / response.data.steps[index-1].count) * 100).toFixed(1) + '%'
      : index === 0 ? '100%' : '0%'
  }));
}

return [];
```

**Expected result:** A table shows each funnel step with user counts and conversion rates. A bar chart visualizes the drop-off at each step. The date range filter updates both components. Funnel bottlenecks are immediately visible from the conversion rate column.

### 5. Join Mixpanel data with your internal database for enriched user profiles

The most powerful use of Retool's multi-resource capability is combining Mixpanel behavioral data with your internal database records. This requires two separate queries and a JavaScript transformer to join them.

First, configure your Mixpanel query to fetch data for users that match the search criteria. Use Mixpanel's Engage API (/engage) to query user profiles by property — for example, finding all users whose email matches the search input:
- Method: GET
- Path: /engage
- URL Parameters:
  - project_id: {{ YOUR_PROJECT_ID }}
  - where: properties["$email"] == "{{ userEmailSearch.value }}"
  - include_all_users: true

In parallel, configure a database query to fetch the same user's internal record from your database using the same email address as the search key.

Create a JavaScript query (no resource required) that combines both results. This query references the outputs of both the Mixpanel query and the database query, joins them by email or distinct_id, and returns an enriched object with fields from both sources.

Bind the enriched object to profile display components in your Retool app: the left column shows database fields (account tier, creation date, subscription status, support ticket count), and the right column shows Mixpanel properties (last seen, total events, key feature usage counts).

```
// JavaScript query to join Mixpanel user profile with internal database record
// This query has no resource - it combines two other query results

const mixpanelUser = mixpanelEngageQuery.data?.results?.[0] || null;
const internalUser = internalUserQuery.data?.[0] || null;

if (!internalUser && !mixpanelUser) {
  return { found: false, message: 'No user found matching that email' };
}

// Extract Mixpanel properties (stored under $properties)
const mpProps = mixpanelUser?.['$properties'] || {};

return {
  found: true,
  // Internal database fields
  account_id: internalUser?.id || null,
  account_tier: internalUser?.plan_tier || 'Unknown',
  created_at: internalUser?.created_at
    ? new Date(internalUser.created_at).toLocaleDateString()
    : 'Unknown',
  support_tickets: internalUser?.support_ticket_count || 0,
  
  // Mixpanel behavioral data
  last_seen: mpProps['$last_seen']
    ? new Date(mpProps['$last_seen']).toLocaleDateString()
    : 'Never tracked',
  total_events_30d: mpProps['total_events_30d'] || 0,
  key_feature_used: mpProps['used_key_feature'] || false,
  country: mpProps['$country_code'] || '',
  
  // Cross-referenced insight
  churn_risk: internalUser?.plan_tier === 'free' && (!mpProps['$last_seen'] 
    || Date.now() - new Date(mpProps['$last_seen']) > 14 * 24 * 60 * 60 * 1000)
    ? 'High' : 'Low'
};
```

**Expected result:** Searching for a user email populates a profile panel combining data from both Mixpanel and the internal database. The combined view shows database account details alongside Mixpanel behavioral properties. The churn risk indicator (derived from both sources) demonstrates the value of the enriched profile over either system alone.

## Best practices

- Create a dedicated Mixpanel service account for Retool with Analyst-level access rather than using a personal user account, so API access can be revoked or rotated independently.
- Store service account credentials in Retool Configuration Variables marked as secret, not hardcoded in the resource configuration, to enable credential rotation without editing resources.
- Always inspect the raw Mixpanel API response in Retool's query panel before writing transformers — Mixpanel's response structure varies significantly across endpoints and API versions.
- Use Retool's 'Only run when' query condition to prevent Mixpanel API queries from firing when required parameters like project_id or date range are not yet set.
- Combine Mixpanel event data with your internal database records using JavaScript transformers — this creates enriched views that are more actionable than either data source alone.
- For dashboards that load on page open, use narrow date ranges (last 7 or 30 days) as defaults — Mixpanel queries for long date ranges are slower and may time out.
- Cache Mixpanel query results in Retool using the query caching feature (set cache duration to 30-60 minutes for dashboards that don't need real-time data) to reduce API calls and improve load times.
- Test Mixpanel API queries with curl or the Mixpanel API Explorer before configuring them in Retool — this isolates authentication issues from Retool configuration issues.

## Use cases

### Build a product engagement overview dashboard

Create a Retool dashboard that queries Mixpanel for daily active users, weekly event counts for key product actions (feature usage, conversions, errors), and displays them alongside trend charts. The dashboard includes filters for date range and user segment, refreshes on demand, and shows a summary table of top events by volume over the selected period. Product managers use this to get a quick health check without logging into Mixpanel.

Prompt example:

```
Build a product analytics dashboard with a date range picker and refresh button. Query Mixpanel's Event Segmentation API for the top 10 events by count over the selected period. Display a bar chart of event volume by day and a table showing each event name, total count, and percentage change from the prior equivalent period.
```

### Create an enriched user profile panel combining Mixpanel and internal data

Build a Retool app where support agents look up a user by email or ID, see all events that user has triggered in Mixpanel over the last 30 days, and view that activity alongside the user's internal database profile, subscription tier, and support ticket count. The joint view enables agents to quickly understand whether a user's support issue correlates with product behavior patterns, accelerating resolution.

Prompt example:

```
Create a user profile panel with an email search input. Query the internal users table for the user's account details. In parallel, query Mixpanel's User API or a JQL query to get that user's recent events. Display the database profile on the left and a chronological Mixpanel activity timeline on the right, joined by the user's distinct_id.
```

### Build a funnel analysis and conversion monitoring tool

Build a Retool panel that queries Mixpanel's Funnel API for a specific conversion funnel (e.g., signup to activation to paid conversion), shows step-by-step conversion rates for the selected time period, and lets the growth team filter by user properties like plan type or acquisition channel. A line chart shows funnel conversion rate trends over time, and the table highlights which funnel steps have the highest drop-off.

Prompt example:

```
Create a funnel monitoring dashboard that calls Mixpanel's Funnel API for the main activation funnel. Show each funnel step with the number of users who reached it and the conversion rate from the previous step. Add a date range filter and a property filter for acquisition_channel. Display a trend line showing weekly funnel completion rate over the past 90 days.
```

## Troubleshooting

### All Mixpanel API queries return 400 Bad Request with 'Invalid project_id' error

Cause: The project_id parameter is set to the Project Token (alphanumeric string starting with a letter) instead of the numeric Project ID, or the project_id parameter is being passed in the request body instead of as a URL query parameter.

Solution: Find your numeric Project ID in Mixpanel → Settings → Project Settings → Overview — it is the number in parentheses next to the project name, not the Project Token. Ensure project_id is passed as a URL query parameter (in Retool's URL Parameters section), not in the request body. The Project Token is a different value used for event ingestion, not for query API authentication.

### Mixpanel queries return 200 but data.values is an empty object even though events exist in Mixpanel

Cause: The date range parameters (from_date, to_date) are in the wrong format, or the event name in the event parameter does not exactly match the event name as tracked in Mixpanel (including case sensitivity).

Solution: Mixpanel's Query API requires date parameters in 'YYYY-MM-DD' string format, not ISO timestamps or Unix timestamps. Verify with a transformer that your date values are formatted correctly: new Date(dateRangePicker.startDate).toISOString().split('T')[0]. For event names, check the exact spelling and case in Mixpanel's Events section — 'Page View' and 'page_view' are different events. Use the List Events endpoint (GET /events/names) to get the exact event name strings from your project.

```
// Ensure correct date format for Mixpanel API
// Use this expression for from_date/to_date parameters
new Date(dateRangePicker.startDate).toISOString().split('T')[0]
```

### Mixpanel Engage API (/engage) returns an empty results array when searching by email

Cause: Mixpanel's Engage API uses a specific filter syntax for the 'where' parameter. Common mistakes include incorrect property names (Mixpanel uses '$email' with a dollar sign for reserved properties) or URL encoding issues with the filter expression.

Solution: Verify the property name used in your where clause matches how the property is named in Mixpanel — check a specific user's profile in Mixpanel to see the exact property names. Reserved properties use dollar-sign prefixes. Also ensure the filter string is URL-encoded — Retool's query editor handles this automatically when you put the value in the URL Parameters section, but if you are manually building the URL string, you may need explicit encoding.

```
// Correct where parameter syntax for Mixpanel Engage API
// Reference this in the URL Parameters section as the 'where' value
// For email search (reserved property with $ prefix):
'properties["$email"] == "' + userEmailInput.value + '"'

// For a custom property (no $ prefix):
'properties["account_id"] == "' + accountIdInput.value + '"'
```

### Transformer for Mixpanel response throws 'Cannot read properties of undefined' on some date ranges

Cause: Mixpanel's API may return an empty data.values object when there are no events in the selected date range, and the transformer is not handling the empty state.

Solution: Add null checks and default values at the start of your transformer to handle empty responses gracefully. Use optional chaining and nullish coalescing to prevent undefined access errors when the response structure is empty.

```
// Add null-safe defaults at the top of any Mixpanel transformer
const response = data;
const eventData = response?.data?.values ?? {};
const eventNames = Object.keys(eventData);
if (eventNames.length === 0) return []; // return empty array, not undefined
```

## Frequently asked questions

### What is the difference between Mixpanel's service account authentication and using an API secret key?

Mixpanel has two API authentication approaches. Legacy API keys (an API secret visible in project settings) use HTTP Basic Auth with the API secret as the username and an empty password. Service accounts (the recommended modern approach) also use HTTP Basic Auth but with a generated username and password scoped to specific projects. Service accounts are preferred because they can be scoped to specific projects, managed independently of user accounts, and revoked without affecting other integrations. Retool's Basic Auth configuration works with both approaches.

### Can Retool query Mixpanel in real time, or is there always a data delay?

Mixpanel's Query API typically has a data latency of a few minutes for recent events, with older data fully processed. The API does not provide a true streaming/real-time feed. For operational dashboards, this latency is usually acceptable. If you need sub-minute data freshness, consider querying your event tracking database directly (if you mirror Mixpanel events to a warehouse) rather than the Mixpanel API.

### What is JQL (JavaScript Query Language) and when should I use it in Retool instead of the standard Mixpanel Query API?

JQL is Mixpanel's custom JavaScript-based query language that allows arbitrary analytical queries by writing JavaScript that processes raw event streams. Use JQL when you need to answer questions that don't fit neatly into the standard endpoints — custom session definitions, complex multi-event sequences, unusual aggregations. The tradeoff is that JQL queries can be slower and require knowledge of the Mixpanel JQL API. For standard event counts, funnels, and retention metrics, the standard Query API endpoints are simpler and faster.

### How do I connect a Mixpanel user's distinct_id to their record in my internal database?

Mixpanel's distinct_id is the identifier your client-side SDK uses to track users. If you set the distinct_id to match your internal user ID (using mixpanel.identify(userId) in your frontend code), you can directly join on that field in a Retool transformer. If distinct_ids are Mixpanel-generated random strings, you need to use the $email property or a custom property that you explicitly set on Mixpanel profiles (using mixpanel.people.set) to match users across systems.

### Can Retool write events back to Mixpanel, or is it read-only?

You can configure a second Retool REST API Resource pointing to Mixpanel's Ingestion API (api.mixpanel.com/track) to send events from Retool apps. This is useful for tracking actions taken within internal tools — for example, logging when a support agent views a user profile or when an operator triggers a refund, creating a full audit trail of internal tool usage in Mixpanel. The Ingestion API uses your Project Token for authentication (not service account credentials), so set up a separate resource for writes.

---

Source: https://www.rapidevelopers.com/retool-integrations/mixpanel
© RapidDev — https://www.rapidevelopers.com/retool-integrations/mixpanel
