Interactive query builder for SQL and JQL queries on Mixpanel data
Build and execute SQL, JQL, segmentation, funnel, or retention queries on Mixpanel data. Use this to analyze user behavior, conversion rates, and retention patterns from your Mixpanel project.
/plugin marketplace add jaredmcfarland/mixpanel_data/plugin install mixpanel-data@mixpanel-datasql|jql|segmentation|funnel|retentionGuide the user through building and executing queries on their Mixpanel data.
Determine query type from $1 or ask the user:
Check what data is available:
!$(mp inspect tables --format table 2>/dev/null || echo "No tables found. Run /mp-fetch first.")
If no tables exist and user selects SQL, suggest running /mp-fetch first or /mp-inspect to explore live schema.
!$(mp inspect tables --format table)
For each table, offer to show:
mp inspect schema -t <table>mp query sql "SELECT * FROM <table> LIMIT 5" --format tablemp inspect breakdown -t <table> --format tableHelp construct the query based on user needs:
Common query patterns:
Event counts by day:
SELECT
DATE_TRUNC('day', event_time) as day,
event_name,
COUNT(*) as count
FROM events
GROUP BY 1, 2
ORDER BY 1 DESC
User activity:
SELECT
COUNT(DISTINCT distinct_id) as unique_users,
COUNT(*) as total_events
FROM events
WHERE event_time >= '2024-01-01'
Property analysis (JSON extraction):
SELECT
properties->>'$.country' as country,
COUNT(*) as events,
COUNT(DISTINCT distinct_id) as users
FROM events
WHERE event_name = 'Purchase'
GROUP BY 1
ORDER BY 2 DESC
Numeric aggregation:
SELECT
DATE_TRUNC('day', event_time) as day,
SUM(CAST(properties->>'$.amount' AS DOUBLE)) as revenue,
AVG(CAST(properties->>'$.amount' AS DOUBLE)) as avg_order
FROM events
WHERE event_name = 'Purchase'
GROUP BY 1
ORDER BY 1
mp query sql "<query>" --format table
Output format options:
--format table - Human-readable (default for exploration)--format json - Machine processing--format csv - Export to spreadsheetFilter JSON output with --jq:
# Filter results with jq
mp query sql "SELECT * FROM events LIMIT 100" --format json \
--jq '.[] | select(.event_name == "Purchase")'
# Extract specific fields
mp query sql "SELECT event_name, COUNT(*) as cnt FROM events GROUP BY 1" \
--format json --jq 'map({name: .event_name, count: .cnt})'
Next steps after query:
/mp-inspect column -t <table> -c <column> for statistics/mp-funnel or /mp-retention for specialized analyticsJQL is for:
Help construct based on analysis needs:
Basic event count:
function main() {
return Events({
from_date: '2024-01-01',
to_date: '2024-01-31'
}).reduce(mixpanel.reducer.count());
}
Group by property:
function main() {
return Events({
from_date: '2024-01-01',
to_date: '2024-01-31',
event_selectors: [{event: 'Purchase'}]
})
.groupBy(['properties.country'], [
mixpanel.reducer.count(),
mixpanel.reducer.sum('properties.amount')
])
.sortDesc('value');
}
User-level analysis:
function main() {
return Events({
from_date: '2024-01-01',
to_date: '2024-01-31'
})
.groupByUser(mixpanel.reducer.count())
.filter(function(item) {
return item.value > 10; // Active users with >10 events
});
}
Save the script to a file (e.g., analysis.js):
mp query jql analysis.js --format table
With parameters:
mp query jql analysis.js \
--param from_date=2024-01-01 \
--param to_date=2024-01-31 \
--format table
Time-series event analysis with optional property breakdown.
--on): Property to break down by (e.g., country, plan)--unit): Time granularity (day, week, month)--where): Filter expressionBasic event trend:
mp query segmentation -e "Purchase" \
--from 2024-01-01 \
--to 2024-01-31 \
--format table
Segmented by property:
mp query segmentation -e "Purchase" \
--from 2024-01-01 \
--to 2024-01-31 \
--on country \
--format table
Filter with --jq:
# Get just the total count
mp query segmentation -e "Purchase" \
--from 2024-01-01 --to 2024-01-31 \
--format json --jq '.total'
# Get top days by volume
mp query segmentation -e "Purchase" \
--from 2024-01-01 --to 2024-01-31 \
--format json --jq '.series | to_entries | sort_by(.value) | reverse | .[:5]'
With filter:
mp query segmentation -e "Purchase" \
--from 2024-01-01 \
--to 2024-01-31 \
--on plan \
--where 'properties["amount"] > 100' \
--format table
Analyze conversion through saved funnel steps.
!$(mp inspect funnels --format table)
Ask user to choose funnel by ID from the list.
mp query funnel <funnel-id> \
--from 2024-01-01 \
--to 2024-01-31 \
--format table
Optional:
--unit day|week|month - Time granularity--on property - Segment by propertyCohort retention analysis.
mp query retention \
--born "Sign Up" \
--return "Login" \
--from 2024-01-01 \
--to 2024-01-31 \
--unit week \
--format table
With filters:
mp query retention \
--born "Sign Up" \
--return "Purchase" \
--from 2024-01-01 \
--to 2024-01-31 \
--born-where 'properties["source"] == "organic"' \
--return-where 'properties["amount"] > 50' \
--format table
After query execution:
--format csv for spreadsheetsFor SQL:
LIMIT during explorationDATE_TRUNC for time-based groupingFor JQL:
event_selectors rather than .filter() when possiblegroupByUser for per-user analysisFor Live Queries:
"No tables found": Run /mp-fetch first to get local data
"Event not found": Check mp inspect events for available events
"Invalid query": Check SQL/JQL syntax in skill reference files
"Rate limit": Wait before retrying live queries
"Authentication error": Run /mp-auth to reconfigure credentials