| name | dc-analysis-config |
| description | Create and configure AnalysisConfig objects for query, funnel, and flow analysis modes in Drizzle Cube dashboards. |
Analysis Config Skill
This skill helps you create AnalysisConfig objects - the canonical format for persisting analysis state in Drizzle Cube. Use AnalysisConfig for:
- Dashboard portlets (via
analysisConfig field)
- Share URLs
- localStorage persistence
AnalysisConfig Overview
interface AnalysisConfig {
version: 1
analysisType: 'query' | 'funnel' | 'flow'
activeView: 'table' | 'chart'
charts: {
[K in AnalysisType]?: ChartConfig
}
query: CubeQuery | MultiQueryConfig | ServerFunnelQuery | ServerFlowQuery
}
interface ChartConfig {
chartType: ChartType
chartConfig: ChartAxisConfig
displayConfig: ChartDisplayConfig
}
Query Mode (analysisType: 'query')
For standard queries and multi-query analysis.
Single Query Example
const singleQueryConfig: QueryAnalysisConfig = {
version: 1,
analysisType: 'query',
activeView: 'chart',
charts: {
query: {
chartType: 'bar',
chartConfig: {
xAxis: ['Employees.department'],
yAxis: ['Employees.count', 'Employees.avgSalary']
},
displayConfig: {
showLegend: true,
stackType: 'none'
}
}
},
query: {
measures: ['Employees.count', 'Employees.avgSalary'],
dimensions: ['Employees.department'],
filters: [
{
member: 'Employees.isActive',
operator: 'equals',
values: [true]
}
],
order: {
'Employees.count': 'desc'
},
limit: 10
}
}
Multi-Query Example
Combine multiple queries with merge strategies:
const multiQueryConfig: QueryAnalysisConfig = {
version: 1,
analysisType: 'query',
activeView: 'chart',
charts: {
query: {
chartType: 'line',
chartConfig: {
xAxis: ['Orders.createdAt'],
yAxis: ['Sales.totalRevenue', 'Returns.totalRefunds']
},
displayConfig: {
showLegend: true,
showGrid: true
}
}
},
query: {
queries: [
{
measures: ['Sales.totalRevenue'],
timeDimensions: [{
dimension: 'Orders.createdAt',
granularity: 'month'
}]
},
{
measures: ['Returns.totalRefunds'],
timeDimensions: [{
dimension: 'Returns.createdAt',
granularity: 'month'
}]
}
],
mergeStrategy: 'merge',
mergeKeys: ['Orders.createdAt'],
queryLabels: ['Revenue', 'Refunds']
}
}
Merge Strategies:
'concat' - Append rows with __queryIndex marker (for separate series)
'merge' - Align data by common dimension key (for combined visualization)
Funnel Mode (analysisType: 'funnel')
For sequential step analysis with conversion tracking.
Funnel Example
const funnelConfig: FunnelAnalysisConfig = {
version: 1,
analysisType: 'funnel',
activeView: 'chart',
charts: {
funnel: {
chartType: 'funnel',
chartConfig: {},
displayConfig: {
funnelStyle: 'funnel',
funnelOrientation: 'horizontal',
showFunnelConversion: true,
showFunnelAvgTime: true
}
}
},
query: {
funnel: {
bindingKey: 'Events.userId',
timeDimension: 'Events.timestamp',
steps: [
{
name: 'Signup',
cube: 'Events',
filter: {
member: 'Events.eventType',
operator: 'equals',
values: ['signup']
}
},
{
name: 'First Purchase',
cube: 'Purchases',
filter: {
member: 'Purchases.amount',
operator: 'gt',
values: [0]
},
timeToConvert: 'P30D'
},
{
name: 'Repeat Purchase',
cube: 'Purchases',
filter: {
member: 'Purchases.isRepeat',
operator: 'equals',
values: [true]
},
timeToConvert: 'P90D'
}
],
includeTimeMetrics: true,
globalTimeWindow: 'P180D'
}
}
}
Cross-Cube Funnel
When the binding key has different names in different cubes:
query: {
funnel: {
bindingKey: [
{ cube: 'Signups', dimension: 'Signups.userId' },
{ cube: 'Purchases', dimension: 'Purchases.customerId' }
],
timeDimension: [
{ cube: 'Signups', dimension: 'Signups.createdAt' },
{ cube: 'Purchases', dimension: 'Purchases.purchaseDate' }
],
steps: [
{ name: 'Signup', cube: 'Signups', filter: {...} },
{ name: 'Purchase', cube: 'Purchases', filter: {...} }
]
}
}
Time Window Formats (ISO 8601 Duration)
| Format | Duration |
|---|
PT1H | 1 hour |
PT24H | 24 hours |
P1D | 1 day |
P7D | 7 days |
P30D | 30 days |
P90D | 90 days |
Flow Mode (analysisType: 'flow')
For bidirectional path analysis with Sankey diagram visualization.
Flow Example
const flowConfig: FlowAnalysisConfig = {
version: 1,
analysisType: 'flow',
activeView: 'chart',
charts: {
flow: {
chartType: 'sankey',
chartConfig: {},
displayConfig: {}
}
},
query: {
flow: {
bindingKey: 'Events.userId',
timeDimension: 'Events.timestamp',
eventDimension: 'Events.eventType',
startingStep: {
name: 'Purchase',
filter: {
member: 'Events.eventType',
operator: 'equals',
values: ['purchase']
}
},
stepsBefore: 3,
stepsAfter: 3,
joinStrategy: 'auto'
}
}
}
Flow Output Modes
| Mode | Description | Use Case |
|---|
sankey | Aggregate by (layer, event_type) | Standard flow visualization, paths converge |
sunburst | Path-qualified nodes | Hierarchical tree, each path unique |
Complete CubeQuery Reference
interface CubeQuery {
measures?: string[]
dimensions?: string[]
timeDimensions?: Array<{
dimension: string
granularity?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
dateRange?: string | [string, string]
fillMissingDates?: boolean
compareDateRange?: (string | [string, string])[]
}>
filters?: Filter[]
order?: { [key: string]: 'asc' | 'desc' }
limit?: number
offset?: number
fillMissingDatesValue?: number | null
}
Filter Operators
type FilterOperator =
| 'equals' | 'notEquals'
| 'contains' | 'notContains' | 'startsWith' | 'endsWith'
| 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'notBetween'
| 'in' | 'notIn'
| 'set' | 'notSet' | 'isEmpty' | 'isNotEmpty'
| 'inDateRange' | 'beforeDate' | 'afterDate'
| 'regex' | 'notRegex'
Filter Examples
{
member: 'Products.category',
operator: 'equals',
values: ['Electronics']
}
{
member: 'Orders.amount',
operator: 'between',
values: [100, 500]
}
{
member: 'Orders.createdAt',
operator: 'inDateRange',
values: ['2024-01-01', '2024-12-31']
}
{
type: 'and',
filters: [
{ member: 'Products.isActive', operator: 'equals', values: [true] },
{
type: 'or',
filters: [
{ member: 'Products.category', operator: 'equals', values: ['A'] },
{ member: 'Products.category', operator: 'equals', values: ['B'] }
]
}
]
}
Supported Chart Types
| Chart Type | Best For | Required Config |
|---|
bar | Comparisons | xAxis, yAxis |
line | Trends over time | xAxis, yAxis |
area | Trends with volume | xAxis, yAxis |
pie | Proportions | yAxis (single measure) |
scatter | Correlation | xAxis, yAxis |
radar | Multi-dimensional | yAxis (multiple measures) |
table | Detailed data | None |
funnel | Conversion flows | Funnel query |
sankey | Path analysis | Flow query |
kpiNumber | Single value | yAxis (single measure) |
kpiDelta | Change indicator | yAxis, previous period |
markdown | Text content | displayConfig.content |
bubble | 3+ dimensions | xAxis, yAxis, sizeField |
activityGrid | Heatmap | dateField, valueField |
Default Config Factories
Use these to create default configs:
import {
createDefaultQueryConfig,
createDefaultFunnelConfig,
createDefaultFlowConfig,
createDefaultConfig
} from 'drizzle-cube/client'
const queryConfig = createDefaultQueryConfig()
const funnelConfig = createDefaultFunnelConfig()
const flowConfig = createDefaultFlowConfig()
const config = createDefaultConfig('query')
Type Guards
import {
isQueryConfig,
isFunnelConfig,
isFlowConfig,
isMultiQuery,
isValidAnalysisConfig
} from 'drizzle-cube/client'
if (isQueryConfig(config)) {
}
if (isFunnelConfig(config)) {
}
if (isFlowConfig(config)) {
}
if (isQueryConfig(config) && isMultiQuery(config)) {
}
if (isValidAnalysisConfig(unknownData)) {
}
Period Comparison
Compare data across time periods:
{
measures: ['Sales.revenue'],
timeDimensions: [{
dimension: 'Sales.createdAt',
granularity: 'month',
dateRange: ['2024-01-01', '2024-03-31'],
compareDateRange: [
['2023-01-01', '2023-03-31']
]
}]
}
Workspace Persistence
For localStorage persistence across mode switches:
interface AnalysisWorkspace {
version: 1
activeType: AnalysisType
modes: {
query?: QueryAnalysisConfig
funnel?: FunnelAnalysisConfig
flow?: FlowAnalysisConfig
}
}
import { createDefaultWorkspace } from 'drizzle-cube/client'
const workspace = createDefaultWorkspace()