WebPivotTable Documentation

WebPivotTable (WPT) is a fully self-contained, embeddable pivot-table and charting component built as a standard Web Component. Drop it into any web page, React app, Vue app, Angular app, or plain HTML file with a single <web-pivot-table> element and a script tag.

Key characteristics:

  • Framework-agnostic — works in Vanilla JS, React, Vue, Angular, Svelte, or any other framework.
  • Three data source modes — Memory (browser-only), Server (DuckDB), and OLAP (MDX/XMLA).
  • AI-powered analytics — connect OpenAI, Claude, Gemini, or any OpenAI-compatible endpoint for natural-language queries and insights.
  • 20 UI languages — locale files loaded lazily from CDN or your own server.
  • Rich chart & grid — 20+ Highcharts chart types, column resizing, freezing, sorting, filtering, conditional formatting, calculated fields.
  • Fully themeable — CSS custom properties, 4 built-in presets (default, dark, ocean, forest), or craft your own.
  • Self-hosted or CDN — ship the bundle yourself or load it from the WPT CDN.

Quick Start

The fastest way to get WPT running is a CDN script tag — one line of HTML, no build step:

<!-- 1. Load the WPT bundle from CDN -->
<script src="https://cdn.webpivottable.com/wpt/latest/wpt.js"></script>

<!-- 1. Load the script -->
<script src="https://cdn.webpivottable.com/wpt/latest/wpt.js"></script>

<!-- 2. Place the element anywhere in your page -->
<web-pivot-table id="wpt" style="width:100%;height:600px"></web-pivot-table>

<!-- 3. Load data and go -->
<script>
  const wpt = document.getElementById('wpt')
  // With static loading, direct calls work immediately
  wpt.setWptFromCsvUrl('/data/sales.csv')
</script>

Or install via npm (includes TypeScript declarations):

npm install webpivottable
// registers <web-pivot-table> as a global custom element
import 'webpivottable'
💡 The npm package auto-registers the <web-pivot-table> custom element when imported. No manual customElements.define() call is needed.
ℹ️ 💡 CRITICAL Timing Rules: When to use wpt:ready vs direct calls:
Static loading (CDN script tag in head) → direct calls work after mounting in ANY framework
Dynamic loading (import(), createElement script) → always use wpt:ready in ANY framework
• ⚠️ Framework doesn't matter — React, Vue, Angular, Svelte all follow the same rule!
• ⚠️ Loading method determines the pattern — not your framework choice

Framework Integration

Vanilla JavaScript

Static loading (script in head) — direct calls work:

<!-- Script loaded statically in head -->
<script src="https://cdn.webpivottable.com/wpt/latest/wpt.js"></script>
<web-pivot-table id="wpt" style="width:100%;height:600px"></web-pivot-table>

<script>
  const wpt = document.getElementById('wpt')
  
  // ✅ Direct calls work with static loading
  wpt.setOptions({ locale: 'en', leavePageWarning: true })
  wpt.setWptFromCsvUrl('https://example.com/data.csv')

  // Listen to events
  wpt.eventBus.on('PIVOT_CHANGED', (payload) => {
    console.log('Pivot changed', payload)
  })
</script>

Dynamic loading (createElement) — must use wpt:ready:

<!-- No script in head -->
<web-pivot-table id="wpt" style="width:100%;height:600px"></web-pivot-table>

<script>
  const wpt = document.getElementById('wpt')
  
  // ✅ Must wait for ready with dynamic loading
  wpt.addEventListener('wpt:ready', () => {
    wpt.setOptions({ locale: 'en' })
    wpt.setWptFromCsvUrl('https://example.com/data.csv')
  }, { once: true })

  // Load script dynamically
  const script = document.createElement('script')
  script.src = 'https://cdn.webpivottable.com/wpt/latest/wpt.js'
  document.head.appendChild(script)
</script>

React

// Install: npm install webpivottable
import { useEffect, useRef } from 'react'
import 'webpivottable'

export function PivotTable({ csvUrl }) {
  const ref = useRef(null)

  useEffect(() => {
    const wpt = ref.current
    if (!wpt) return

    // ✅ With npm import (dynamic loading), direct calls work after mounting
    wpt.setOptions({
      locale: 'en',
      uiFlags: { export: true, save: true },
    })
    wpt.setWptFromCsvUrl(csvUrl)
    
    // 💡 Only need wpt:ready if you dynamically load the script with createElement/import()

    // Subscribe to events
    const unsub = wpt.eventBus.on('DRILL_THROUGH', (detail) => {
      console.log('Drill-through:', detail)
    })

    return () => {
      unsub()
    }
  }, [csvUrl])

  return (
    <web-pivot-table
      ref={ref}
      style={{ width: '100%', height: '600px', display: 'block' }}
    />
  )
}
💡 React Integration: With npm install (shown above), direct calls work immediately after mounting. Only use wpt:ready if you dynamically load the script with createElement() or import(). The timing rule is universal across all frameworks!
ℹ️ TypeScript: webpivottable v7.1.1+ includes complete TypeScript definitions. Import type { WebPivotTableElement } from 'webpivottable' for full type safety.

Vue 3

<template>
  <web-pivot-table ref="wptRef" style="width:100%;height:600px" />
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import 'webpivottable'

const wptRef = ref(null)
let unsub: (() => void) | null = null

onMounted(() => {
  const wpt = wptRef.value as any
  
  // Vue can call methods directly after mounting
  wpt.setOptions({ locale: 'en' })
  wpt.setWptFromCsvUrl('/data/sales.csv')
  unsub = wpt.eventBus.on('PIVOT_CHANGED', () => console.log('changed'))
})

onUnmounted(() => unsub?.())
</script>

Angular

// app.module.ts — allow unknown custom elements
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@NgModule({ schemas: [CUSTOM_ELEMENTS_SCHEMA] })
export class AppModule {}

// component.ts
import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core'
import 'webpivottable'

@Component({
  template: '<web-pivot-table #wpt style="width:100%;height:600px"></web-pivot-table>',
})
export class PivotComponent implements AfterViewInit {
  @ViewChild('wpt') wptRef!: ElementRef

  ngAfterViewInit() {
    const wpt = this.wptRef.nativeElement
    
    // Angular can call methods directly after view init
    wpt.setOptions({ locale: 'en' })
    wpt.setWptFromCsvUrl('/data/sales.csv')
  }
}

Svelte

<script>
  import { onMount } from 'svelte'
  import 'webpivottable'

  let wptEl

  onMount(() => {
    // Svelte can call methods directly after mount
    wptEl.setOptions({ locale: 'en' })
    wptEl.setWptFromCsvUrl('/data/sales.csv')
  })
</script>

<web-pivot-table bind:this={wptEl} style="width:100%;height:600px" />

Multiple instances on one page

WPT supports any number of <web-pivot-table> elements on the same page. Each instance is completely isolated — its own Zustand store, its own event bus, its own data.

<!-- Static loading example -->
<script src="https://cdn.webpivottable.com/wpt/latest/wpt.js"></script>
<web-pivot-table id="wpt1" style="width:50%;height:500px;float:left"></web-pivot-table>
<web-pivot-table id="wpt2" style="width:50%;height:500px;float:left"></web-pivot-table>

<script>
  const wpt1 = document.getElementById('wpt1')
  const wpt2 = document.getElementById('wpt2')
  
  // Direct calls work with static loading
  wpt1.setWptFromCsvUrl('/sales.csv')
  wpt2.setWptFromCsvUrl('/inventory.csv')
</script>

Locale & Internationalization

Available languages

WPT ships with bootstrap strings for English and Chinese built in. Full translations for 20 languages are loaded lazily from the CDN (or your own server):

CodeLanguageCodeLanguage
enEnglish (default)zhChinese (Simplified)
deGermanfrFrench
esSpanishptPortuguese
itItaliantrTurkish
jaJapanesekoKorean
ruRussianplPolish
nlDutchsvSwedish
arArabiccsCzech
huHungarianroRomanian
daDanishfiFinnish

Setting the locale

// Set via options (recommended)
wpt.setOptions({ locale: 'fr' })

// Or call the dedicated method (async — waits for locale file to load)
await wpt.setLocale('fr')

// Or set as the initial options attribute
<web-pivot-table options='{"locale":"de"}'></web-pivot-table>

Locale file base URL

By default locale files are loaded from https://cdn.webpivottable.com/wpt/latest/locales. Override with localeBaseUrl to self-host translations:

wpt.setOptions({
  locale: 'ja',
  localeBaseUrl: 'https://my-cdn.example.com/wpt-locales',
  // WPT will fetch: https://my-cdn.example.com/wpt-locales/ja.json
})
💡 Copy locale JSON files from node_modules/web-pivot-table/locales/ to your own CDN bucket to avoid any dependency on the WPT CDN.

Options Reference

All options are passed via wpt.setOptions(opts) (merges with existing options) or as the options HTML attribute (JSON string). TypeScript types are exported from web-pivot-table as WptOptions.

Locale options

OptionTypeDefaultDescription
localestring'en'UI language code. See locale table above.
localeBaseUrlstringCDN URLBase URL for locale JSON files. Override to self-host.
leavePageWarningbooleanfalseShow a browser 'leave page?' prompt if the user has unsaved changes.

Behaviour options

OptionTypeDefaultDescription
deferLayoutUpdatebooleanfalseDon't recompute the pivot automatically on every field change — wait for the user to click Refresh. Useful for large datasets.
deferLayoutExcludeFilterbooleanfalseWhen deferLayoutUpdate is true, still update immediately when filters change.
defaultToDistinctCountbooleanfalseWhen a STRING field is dragged to the Values zone, default its aggregation to Distinct Count instead of Count.
drillThroughBySingleClickbooleanfalseSingle-click a data cell to trigger drill-through. Default is double-click.
defaultValueFormatobjectDefault number format for new value fields: { category: 'NUMBER' | 'CURRENCY' | 'PERCENTAGE', negative: 'MINUS' | 'PARENTHESES' | ... }
decimalPointstring'.'Character used as decimal separator in formatted output (e.g. ',' for European locales).
thousandsSepstring','Character used as thousands separator in formatted output (e.g. '.' for European locales).
licenseKeystringLicense key purchased at webpivottable.com/pricing. Hides the 'Powered by WPT' watermark when valid.
initialWptstring | objectPre-load a saved .wpt file on component init. Value can be a JSON string or a parsed object.

Server / proxy options

Configure these under the server key for all data-source proxy settings:

wpt.setOptions({
  server: {
    // File proxy — routes CSV/Excel/JSON fetches through your server
    fileProxyEnabled: true,
    fileProxy: 'https://api.example.com/wpt-proxy/file',
    fileTimeout: 30000,          // ms

    // XMLA proxy — routes OLAP MDX requests through your server
    xmlaProxyEnabled: true,
    xmlaProxy: 'https://api.example.com/wpt-proxy/xmla',
    xmlaTimeout: 60000,

    // HTTP Basic Auth for file proxy
    basicAuthEnabled: false,
    username: '',
    password: '',

    // OLAP roles (semicolon-separated role names)
    rolesEnabled: false,
    roles: 'SalesRole;ReportingRole',
  }
})

Control panel options

OptionTypeDefaultDescription
controlPanel.showbooleantrueShow or hide the right-side control panel on startup.
controlPanel.floatingbooleanfalseFloat the panel over the grid instead of pushing it aside.
controlPanel.position'left' | 'right''right'Side where the control panel docks.
controlPanel.widthnumber280Width of the control panel in pixels.

Layout options

OptionTypeDefaultDescription
layout.fitMode'fill' | 'contain' | 'cover''fill'How the component fills its container.
layout.headerReservenumberExtra pixel reserve for sticky header rendering.
fullscreenbooleanfalseToggle fullscreen programmatically.

Limit options

OptionTypeDefaultDescription
limit.sourceDataMaxRowsnumberHard cap on rows imported from a CSV/Excel file.
limit.sourceDataMaxColumnsnumberHard cap on columns imported from a CSV/Excel file.
limit.sheetLayoutMaxRowsnumberMaximum rows rendered in the pivot grid.
limit.sheetLayoutMaxColumnsnumberMaximum columns rendered in the pivot grid.
limit.olapDrillThroughMaxRowsnumber1000Max rows returned from an OLAP drill-through query.

Grid callback options

Per-row and per-cell style callbacks. These must be set programmatically (not serialized in .wpt files):

wpt.setOptions({
  gridCallbacks: {
    // Style an entire row based on its data
    rowStyleFn: (flatRow, rowIndex) => {
      if (flatRow.region === 'APAC') return { backgroundColor: '#e8f4f8' }
    },
    // Style a specific cell based on its column
    cellValueStyleFn: (flatRow, col) => {
      if (col.id === 'profit' && flatRow.profit < 0)
        return { color: '#d32f2f', fontWeight: 700 }
    },
  },
})

UI Flags

The uiFlags option object controls which toolbar buttons and UI elements are visible. All flags default to true (visible) unless noted otherwise.

wpt.setOptions({
  uiFlags: {
    // Toolbar visibility
    export: true,            // Export button
    save: true,              // Save WPT button
    reset: true,             // Reset button
    fullScreen: true,        // Fullscreen toggle
    language: true,          // Language selector
    source: true,            // Data source button
    open: true,              // Open WPT file
    connectSource: true,     // Connect data source dialog
    sourceExport: true,      // Export in source view
    drillThroughExport: true,// Export in drill-through view

    // Load-source sub-flags
    loadFromCsv: true,
    loadFromExcel: true,
    loadFromGss: false,      // Google Sheets (requires API key)
    loadFromWs: true,        // Web service / REST endpoint
    loadFromOlap: true,

    // Save sub-flags
    saveToLocal: true,
    saveToServer: false,

    // Behaviour flags
    gridChartSwitchOnToolbar: false, // Put Grid/Chart toggle in toolbar
    hideToolbar: false,              // Hide the entire toolbar
    hideFieldSettings: false,        // Disable field settings dialog
    hideValueFieldSettings: false,   // Disable value field settings
    hideConditionalFormat: false,    // Disable conditional format
    hideCalculatedField: false,      // Disable calculated fields
    hideAiChat: false,               // Hide the AI chat tab
    fieldsPanel: true,               // Show field list in control panel
    fieldsPanelSetting: true,        // Show options tab in control panel

    // Prompts
    dropPrompt: true,                // Show "drop file here" prompt
    pivotPrompt: true,               // Show "drag fields" prompt
  }
})

Themes & Styling

WPT supports four built-in theme presets and full CSS custom-property overrides.

Built-in presets

wpt.setOptions({
  theme: { preset: 'default' }   // 'default' | 'dark' | 'ocean' | 'forest'
})

Custom colors

wpt.setOptions({
  theme: {
    preset: 'default',         // start from a preset
    colors: {
      primary: '#7c3aed',      // brand / accent color
      primaryText: '#fff',
      background: '#f9fafb',
      backgroundPanel: '#ffffff',
      border: '#e5e7eb',
      text: '#111827',
      textSecondary: '#6b7280',
      gridHeaderBackground: '#f3f4f6',
      gridHeaderText: '#111827',
    },
    typography: {
      fontSize: '13px',
      lineHeight: 1.5,
    },
    shape: {
      borderRadius: '6px',
    },
  },
})

Memory Mode (CSV / Excel / JSON)

In Memory mode all data is loaded into the browser and processed client-side. No server required. Suitable for files up to approximately 100 MB (browser-dependent).

Supported input formats: CSV, TSV, Excel (.xls / .xlsx), JSON arrays, Google Sheets (public).

Load from URL

// CSV
wpt.setWptFromCsvUrl('/data/sales.csv')

// Excel
wpt.setWptFromExcelUrl('/data/report.xlsx')

// Web service returning JSON ({ fields:[...], data:[...] })
wpt.setWptFromWebService('https://api.example.com/pivot-data')

// Google Sheet (public, published to the web)
wpt.setWptFromGoogleSpreadSheet(
  'https://docs.google.com/spreadsheets/d/SHEET_ID/export?format=csv'
)

Load from a JavaScript array

// attrArray = field definitions, dataArray = rows
const attrArray = [
  { name: 'Region',  type: 'STRING' },
  { name: 'Quarter', type: 'STRING' },
  { name: 'Revenue', type: 'NUMBER' },
]
const dataArray = [
  ['APAC', 'Q1', 120000],
  ['EMEA', 'Q1',  98000],
  ['APAC', 'Q2', 135000],
]
wpt.setWptFromDataArray(attrArray, dataArray)

Load from a local file (file picker / drag-and-drop)

document.getElementById('fileInput').addEventListener('change', async (e) => {
  const file = e.target.files[0]
  await wpt.setWptFromLocalFile(file)  // type auto-detected from extension
})

Cross-origin files — using a file proxy

If the CSV/Excel file is on a different origin, configure a file proxy on your server that forwards the request and sets CORS headers:

wpt.setOptions({
  server: {
    fileProxyEnabled: true,
    fileProxy: '/api/wpt-proxy/file',  // your server-side proxy endpoint
  }
})

// Now cross-origin URLs work:
wpt.setWptFromCsvUrl('https://data.example.com/report.csv')

The proxy endpoint receives a POST with a url parameter, fetches the file server-side, and returns the content with appropriate CORS headers.

Server Mode (DuckDB)

In Server mode data stays on your server and is queried by DuckDB. The browser sends structured pivot queries; the server returns only aggregated results. Raw data never reaches the browser — ideal for sensitive data and very large files.

ℹ️ Server mode is built into Datira.ai. To use it in your own deployment, you need a WPT-compatible DuckDB server endpoint. Contact us for the server-side reference implementation.

Connecting to a server mode source

// Server mode source is set up server-side; the client receives a sourceId
// that references the pre-loaded dataset on the server.
wpt.setSourceObject({
  mode: 'SERVER',
  sourceId: 'abc123',          // returned by your server after upload
  name: 'Sales 2024',
  fields: [...],               // field definitions from server
})

OLAP Mode (MDX / XMLA)

OLAP mode connects WPT directly to a multidimensional OLAP cube via the XMLA protocol. Compatible with Microsoft SSAS, SAP BW, Apache Kylin, Mondrian, ClickHouse, and any XMLA-compliant server.

Connecting to an OLAP cube

wpt.setWptFromOlapCube({
  xmlaUrl: 'https://my-ssas-server/olap/msmdpump.dll',
  catalogName: 'AdventureWorks',
  cubeName: 'Sales',
})

// With a proxy (required for CORS or authentication)
wpt.setOptions({
  server: {
    xmlaProxyEnabled: true,
    xmlaProxy: '/api/wpt-proxy/xmla',
    basicAuthEnabled: true,
    username: 'analyst',
    password: 'secret',
  }
})

OLAP cube config object

FieldTypeDescription
xmlaUrlstringXMLA endpoint URL of the OLAP server.
catalogNamestringDatabase / catalog name on the OLAP server.
cubeNamestringCube name within the catalog.

WPT File Format

A .wpt file is a plain JSON object that captures the complete state of a WebPivotTable session: data source configuration, pivot field layout, display options, and optionally the raw data itself.

{
  "version": "7.0",
  "source": {
    "mode": "MEMORY",     // "MEMORY" | "SERVER" | "OLAP"
    "type": "CSV",        // "CSV" | "EXCEL" | "WSDATA" | "CUBE" | "WPT"
    "name": "sales.csv",
    "url": "https://...",
    "fields": [
      { "id": "0", "name": "Region",  "type": "STRING", "cellIndex": 0 },
      { "id": "1", "name": "Revenue", "type": "NUMBER", "cellIndex": 1 }
    ],
    // Optional embedded data (set ignoreData:true to omit)
    "data": [[...], [...]]
  },
  "sheet": {
    "pivot": {
      "rows": ["0"],
      "columns": [],
      "filters": [],
      "values": [{ "id": "v0", "fieldId": "1", "name": "Sum of Revenue",
                   "stats": "SUM", "format": { "category": "CURRENCY" } }],
      "fields": {
        "0": { "sort": { "sortType": "LABEL", "sortDescend": 0 } }
      }
    },
    "options": {
      "displayMode": "grid",
      "grid": { "fixedRows": 1, "fixedColumns": 1 },
      "chart": { "type": "bar", "theme": "default" }
    }
  }
}

Save and load programmatically

// Save — get a JSON string
const jsonStr = wpt.generateWptString()          // includes data
const noDataStr = wpt.generateWptString(true)    // excludes data (smaller)

// Save — get a JavaScript object
const jsonObj = wpt.generateWptJSON()

// Load from string / object
wpt.setWpt(JSON.parse(jsonStr))

// Load from URL
wpt.setWptFromWptUrl('/saved/report.wpt')

Getting an Instance

// By id
const wpt = document.getElementById('my-wpt')

// By querySelector
const wpt = document.querySelector('web-pivot-table')

// All instances on the page
const all = document.querySelectorAll('web-pivot-table')

// In React — via ref
import { useRef } from 'react'
const ref = useRef(null)
// ref.current is the element after mount

// Check the WPT version
console.log(wpt.version)   // e.g. "7.0.0"

Data Methods

SignatureDescription
getData() → WptDataRow[]Returns the current in-memory raw data rows.
setData(rows: WptDataRow[]) → voidReplace the current in-memory data with a new array of rows. Use setWptFromDataArray to also re-configure fields.
getSourceObject() → objectReturns the full internal source object (fields, data, mode, etc.).
setSourceObject(src: object) → voidDirectly replace the internal source object. Advanced — use source methods when possible.
getFieldCatalog() → FieldDescriptor[]Returns structured field metadata: name, type, distinct count, sample values, and current zone. Ideal for feeding an LLM.

Source Methods

Methods that load data and connect data sources. All are async (return a Promise).

SignatureDescription
setWptFromCsvUrl(url, delimiter?)Fetch and parse a CSV file from a URL. delimiter defaults to ','.
setWptFromExcelUrl(url)Fetch and parse an Excel (.xls/.xlsx) file from a URL.
setWptFromWebService(url)Fetch JSON data from a REST endpoint returning { fields, data } or an array of row objects.
setWptFromGoogleSpreadSheet(url)Load a public Google Sheet (published as CSV).
setWptFromDataArray(attrArray, dataArray)Load from JavaScript arrays. attrArray = [{name, type}], dataArray = rows.
setWptFromOlapCube(config)Connect to an XMLA OLAP cube. config = { xmlaUrl, catalogName, cubeName }.
setWptFromLocalFile(file, type?)Load from a File object (drag-drop or <input type=file>). Type auto-detected from extension.
setWptFromWptUrl(url)Load a saved .wpt JSON file from a URL.
setWpt(wptObject)Load from a parsed .wpt JSON object.
generateWptString(ignoreData?)Serialize current state to a JSON string. Pass true to omit raw data.
generateWptJSON(ignoreData?)Same as above but returns a plain JS object instead of a string.

get-only counterparts

Every setWptFrom* method has a getSourceFrom* counterpart that parses and returns the source object without loading it into the component. Useful for pre-loading or validating data before display.

const source = await wpt.getSourceFromCsvUrl('/data.csv')
// inspect source.fields, source.data...
wpt.setSourceObject(source)   // then load when ready

Pivot Methods

SignatureDescription
getPivotState() → objectReturns the current pivot configuration: { rows, columns, filters, values, fields }.
configurePivot(config) → voidSet the pivot configuration programmatically. Same shape as getPivotState() output.
getPivotSummary() → objectReturns a human-readable summary of the current pivot (field names, stats, display mode).
swapAxis() → voidSwap the rows and columns zones.
clearAllPivot() → voidRemove all fields from all zones (rows, columns, filters, values).
clearAllFilters() → voidRemove all active filters without changing zone assignments.
refresh() → voidForce re-compute the pivot. Useful when data changes externally.

Pre-configuring a pivot layout

// After loading data, automatically set up rows/columns/values:
await wpt.setWptFromCsvUrl('/data/sales.csv')

wpt.configurePivot({
  rows:    ['region_id'],        // field ids from source.fields
  columns: ['quarter_id'],
  values:  [{
    id: 'v1',
    fieldId: 'revenue_id',
    name: 'Total Revenue',
    stats: 'SUM',
    format: { category: 'CURRENCY', decimal: 0 },
  }],
})

Lifecycle & UI Methods

SignatureDescription
setOptions(opts) → WptOptionsMerge new options into the current options and re-render. Returns the merged options object.
getOptions() → WptOptionsReturns the current options object.
setLocale(lng) → Promise<void>Switch the UI language. Loads the locale file if not already cached.
getLocale() → stringReturns the current locale code (e.g. 'en').
reset() → voidClear all data and return to the initial empty state.
resize() → voidTrigger a layout measurement. Call after programmatically resizing the container element.
setSize(w, h) → voidSet the element's CSS width/height. Accepts numbers (pixels) or CSS strings ('100%', '600px').
getSize() → {width, height}Returns the current rendered dimensions in pixels.
showLoading() → voidShow the loading overlay.
hideLoading() → voidHide the loading overlay.
loadingMessage(msg) → voidShow a custom loading message in the overlay.
errorMessage(msg) → voidShow an error message overlay.
clearMessage() → voidDismiss any active message overlay.
showControlPanel() → voidExpand the right-side control panel.
hideControlPanel() → voidCollapse the control panel.
toggleControlPanel() → voidToggle the control panel open/closed.

Export Methods

Export methods are available on the WPT element. All are synchronous unless noted.

SignatureDescription
exportGridToExcel(filename?)Export the current pivot grid to a .xlsx Excel file. filename defaults to 'PivotGrid'.
exportGridToPdf(filename?)Export the pivot grid to a .pdf file.
exportGridToHtml(filename?)Export the pivot grid to a static .html file.
printGrid()Print the pivot grid using the browser print dialog.
exportChartToImage(filename?)Export the current chart as a PNG file.
exportChartToPdf(filename?)Export the current chart as a PDF (async).
printChart()Print the current chart using an isolated iframe.
exportSourceToExcel(filename?)Export the raw source data to a .xlsx file.
exportSourceToCsv(filename?)Export the raw source data as a .csv file.
printSource()Print the raw source data table.
getDisplayMode() → 'grid' | 'chart' | 'both'Returns the current display mode.
// Export the grid to Excel
wpt.exportGridToExcel('SalesReport_2024')

// Export the chart as a PNG
wpt.exportChartToImage('SalesChart_Q4')

Event Bus

Each WPT instance has its own isolated event bus accessible via wpt.eventBus. Use it to listen to user interactions and component state changes without modifying WPT internals.

Event types

EventPayloadWhen fired
PIVOT_CHANGED{ sheet, source }Any time the pivot layout changes (field move, filter, sort, etc.).
DATA_LOADED{ source }After a data source is successfully loaded.
DRILL_THROUGH{ sheet, row, column }User double-clicks (or single-clicks if configured) a data cell.
OPEN_WPTstringUser triggers the Open WPT action.
SAVE_WPTstringUser triggers the Save WPT action.
NEW_WPTstringUser resets to a blank state.
CONNECT_SOURCEstringUser opens the Connect Data Source dialog.

Subscribing to events

const wpt = document.getElementById('wpt')

// Subscribe — returns an unsubscribe function
const unsub = wpt.eventBus.on('PIVOT_CHANGED', ({ sheet, source }) => {
  console.log('Rows:', sheet.pivot.rows)
  console.log('Values:', sheet.pivot.values)
})

// Unsubscribe when done
unsub()

// Or use .off() explicitly
const handler = (payload) => console.log(payload)
wpt.eventBus.on('DATA_LOADED', handler)
wpt.eventBus.off('DATA_LOADED', handler)

Intercepting Save / Open with custom logic

// Override Save — store the WPT JSON in your own backend
wpt.eventBus.on('SAVE_WPT', async () => {
  const json = wpt.generateWptString()
  await fetch('/api/reports/save', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: json,
  })
  alert('Report saved!')
})

// Override Open — load from your own backend
wpt.eventBus.on('OPEN_WPT', async () => {
  const res = await fetch('/api/reports/latest')
  const json = await res.json()
  wpt.setWpt(json)
})

DOM CustomEvents (alternative to eventBus)

All event bus events are also dispatched as native DOM CustomEvents on the element itself, so you can use addEventListener instead of the event bus:

document.getElementById('wpt').addEventListener('PIVOT_CHANGED', (e) => {
  console.log(e.detail)   // same payload as eventBus
})

AI Integration — Setup & Providers

WPT has a built-in AI assistant that understands your data, answers natural-language questions, configures the pivot automatically, generates narrative insights, explains cell values, and detects statistical anomalies.

Enabling AI

wpt.setOptions({
  ai: {
    enabled: true,
    provider: 'openai',          // 'openai' | 'anthropic' | 'google' | 'custom'
    apiKey: 'sk-...',            // your API key (client-side — consider a proxy for production)
    model: 'gpt-4o-mini',        // model name
    temperature: 0.3,            // 0.0 – 1.0
    maxTokens: 1500,

    // Optional: route through your own backend to hide the API key
    endpoint: 'https://api.example.com/ai-proxy',

    // Optional: context ID used for multi-instance differentiation
    contextId: 'report-v1',

    // Optional: custom system prompt prepended to every request
    systemPrompt: 'You are a financial data analyst...',

    // UI
    showChatPanel: true,         // open the AI chat tab on load
    showInsightButton: true,     // show "Generate Insights" button
  }
})

Provider & endpoint reference

ProviderExample modelendpoint
OpenAIgpt-4o-mini, gpt-4ohttps://api.openai.com/v1 (default)
Anthropicclaude-3-5-sonnet-20241022https://api.anthropic.com/v1
Googlegemini-1.5-flashhttps://generativelanguage.googleapis.com/v1beta
CustomanyAny OpenAI-compatible endpoint URL
⚠️ Never ship your AI API key in client-side code for production. Set endpoint to a backend proxy that injects the key server-side.

AI Features

Natural language pivot configuration

The AI chat panel lets users ask questions in plain language. WPT sends the current field catalog (field names, types, sample values) as context. When the AI returns a configurePivot action, the pivot updates automatically.

// Open the AI tab programmatically
wpt.setOptions({ ai: { showChatPanel: true } })

// Or send a message from code
await wpt.aiSendMessage('Show revenue by quarter as a bar chart')
await wpt.aiSendMessage('Filter to APAC region only and sort by revenue descending')

AI Insights

Generate a narrative summary of the currently displayed pivot data:

await wpt.aiGenerateInsights()
const text = wpt.aiGetInsights()
console.log(text)
// → "Revenue grew 23% YoY in APAC, led by Q3 at $342K. EMEA underperformed..."

Cell explanation

// Click a cell in the grid to auto-populate, or pass context directly:
await wpt.aiExplainCell({
  value: 342000,
  fmtValue: '$342,000',
  rowLabel: 'APAC',
  colLabel: 'Q3 2024',
})

Anomaly detection (client-side, free)

Z-score based anomaly detection runs entirely in the browser — no LLM calls, no API cost:

const anomalies = wpt.aiDetectAnomalies({ threshold: 2.5 })
// → [{ row: 'APAC', column: 'Q3', value: 342000, zScore: -2.8, direction: 'low' }]

AI API Methods

SignatureDescription
aiSendMessage(msg) → Promise<void>Send a natural-language message to the AI assistant.
aiGetMessages() → Message[]Returns the full chat history: [{role:'user'|'assistant', content, action?}]
aiClearHistory() → voidClear the AI chat history.
aiIsProcessing() → booleanReturns true if the AI is currently generating a response.
aiGenerateInsights() → Promise<void>Generate a narrative summary of the current pivot data.
aiGetInsights() → string | nullReturns the most recently generated insights text.
aiExplainCell(cellContext) → Promise<void>Ask the AI to explain a specific cell value.
aiDetectAnomalies(opts?) → Anomaly[]Detect outliers using z-score analysis. Client-side, no LLM call.

Control Panel

The right-side control panel has three tabs: Fields, Options, and (when AI is enabled) AI.

Fields tab

  • Field list (top half) — all available fields from the data source with type icons and value counts. Search and sort the list. Check a field to add it to the pivot automatically.
  • Zone panels (bottom half) — drag fields from the list into Filters, Columns, Rows, or Values zones. Drag within a zone to reorder. Drag across zones to move.
  • Defer Update checkbox — enable to batch changes; press Refresh to apply.
  • Field settings — click the edit icon next to any field to open its settings: custom name, sort order, label/value/top-bottom filters, date grouping.
  • Value field settings — click the edit icon on a Value field for: summarization (Sum/Count/Avg/etc.), Show Values As (% of total, running total, etc.), number format, display as number or sparkline.

Options tab

Shared pivot options plus display-mode-specific grid or chart options:

  • Display mode: Grid / Chart
  • Grid: freeze rows/columns, column widths, row height, show/hide totals and subtotals, conditional formatting
  • Chart: chart type, theme, legend position, data labels, stacking

AI tab

Chat interface where users type natural language queries. Responses may include explanatory text and/or automatic pivot reconfigurations.

Pivot Features

Aggregation (Value Field Settings)

FunctionNotes
SumDefault for numeric fields
CountCount all non-null values
Distinct CountCount unique values
AverageArithmetic mean
Min / MaxMinimum / maximum value
MedianMiddle value
ModeMost frequent value
Std DevStandard deviation
VarianceStatistical variance
Percentile (Inc/Exc)Nth percentile, configurable

Show Values As

  • No calculation (raw value)
  • % of Grand Total
  • % of Column Total
  • % of Row Total
  • % of Parent Column Total
  • % of Parent Row Total
  • Running Total by Row
  • Running Total by Column

Field features

  • Custom names — rename any field in the pivot without modifying source data.
  • Sort — sort row/column labels alphabetically (A→Z or Z→A) or by a specific value field.
  • Label filter — manually include/exclude values, or define a formula (contains, begins with, between, etc.).
  • Value filter — filter rows/columns where a value field meets a condition.
  • Top/Bottom filter — show only the top or bottom N items by a value.
  • Date grouping — group date fields by Year, Quarter, Month, Week, or Day.
  • Hide subtotals — suppress subtotal rows/columns for any dimension.
  • Calculated fields — add formula-based computed fields (e.g. Revenue - Cost).

Number formatting

Each value field can have an independent number format:

  • General (raw value)
  • Number (decimal places, thousands separator)
  • Currency (symbol, prefix/suffix, decimal places)
  • Percentage (decimal places)
  • Negative number styles: -1234, (1234), red text variants

Chart & Grid Features

Chart types (powered by Highcharts)

20+ chart types available: Column, Bar, Line, Area, Area-Spline, Spline, Scatter, Bubble, Pie, Donut, Funnel, Pyramid, Gauge, Heatmap, Treemap, Waterfall, Box Plot, Error Bar, 3D variants, and more.

Grid features

  • Freeze rows / columns — sticky header rows and left-side row headers while scrolling.
  • Column resize — drag column borders to resize. Double-click to auto-fit.
  • Row/column totals — grand totals and subtotals with configurable position (top/bottom, left/right).
  • Conditional formatting — color scale, data bars, and icon sets on value cells.
  • Drill-through — double-click a data cell to see the underlying raw rows.
  • Sparklines — display value fields as inline sparkline charts instead of numbers.
  • Cell style callbacks — programmatically style rows and cells via gridCallbacks.
  • Expand/collapse — multi-level row/column headers can be expanded or collapsed.
  • OLAP drill-through — execute DRILLTHROUGH MDX statements for OLAP cubes.

Watermark & License Key

The Community (free) license displays a small "Powered by WPT" badge in the bottom-right corner of the component. This badge links to webpivottable.com and is required by the Community license terms.

Developer, Team, and Enterprise licenses include a license key that permanently hides the watermark for the domain(s) it covers.

Setting your license key

// Via options (most common)
wpt.setOptions({
  licenseKey: 'WPT-eyJwbGFuIjoiZGV2ZWxvcGVyIi...signature'
})

// Or as the HTML attribute
<web-pivot-table
  options='{"licenseKey":"WPT-eyJwbGFuIjoi..."}'
></web-pivot-table>

How the key works

  • The key is a signed JWT-like token: WPT-<base64(payload)>.<hmac-sha256>
  • The payload encodes: plan tier, email, allowed domains, seat count, and issue date.
  • Validation is 100% offline — no network call, no license server. The HMAC is verified client-side using a secret baked into the WPT build.
  • Keys are domain-locked: a key for acme.com will not hide the watermark on a different domain. localhost always passes (dev convenience).
  • Wildcard domains are supported: *.acme.com covers all subdomains.

Console messages

If the key is invalid, a helpful console warning explains why:

// Possible [WPT License] messages:
// "License key format is invalid. Keys must start with 'WPT-'."
// "License key signature does not match."
// "License key is not valid for this domain (your-domain.com)."
// "License key has expired."}

View pricing plans →

Release Notes

v7.0 — March 2026

Major architectural rewrite. Fully backward-compatible API.

  • React + Zustand core — rewritten in React with isolated per-instance Zustand stores. Multiple instances on one page are fully supported with zero cross-fire.
  • Web Component standard — ships as a standard customElements element. No Shadow DOM; inline styles only — no global CSS leakage.
  • TypeScript — full TypeScript support with exported type declarations.
  • AI integration — built-in LLM assistant supporting OpenAI, Anthropic, Google, and any OpenAI-compatible endpoint.
  • Server mode (DuckDB) — new server-side compute mode via DuckDB. Aggregated results only; raw data never leaves the server.
  • Highcharts 11 — updated charting engine with 20+ chart types.
  • Themes — four built-in theme presets (default, dark, ocean, forest) with full CSS custom-property overrides.
  • Running totals — new Show Values As options: Running Total by Row / Column.
  • Sparklines — value fields can be displayed as inline sparkline charts.
  • Conditional formatting — color scale, data bars, and icon sets.
  • 20 languages — full locale support with lazy-loaded external locale files.
  • License system — HMAC-SHA256 domain-locked license keys. Offline validation; no license server.
  • Undo/Redo — full pivot state undo/redo (Ctrl+Z / Ctrl+Y).
  • Anomaly detection — client-side z-score anomaly detection, no LLM cost.
  • Cell explain — AI cell explanation popover on hover/click.
  • Date grouping — group date fields by Year, Quarter, Month, Week, Day.
  • Calculated fields — formula editor for computed fields.

v6.x (legacy)

  • Vue 2-based implementation. No longer actively maintained.
  • v7 is fully backward-compatible at the API level — setWptFromCsvUrl, setOptions, generateWptString, etc. work identically.
  • v6 .wpt files are supported by v7 (legacy format auto-upgraded on load).

Support

Community support (free)

Commercial support (licensed customers)

  • Priority email support — included with Developer and Team licenses. Response within 1 business day.
  • Dedicated support + SLA — included with Enterprise. Direct line to the engineering team.
  • Contactwebpivottable.com/contact

Datira.ai — the hosted SaaS alternative

Don't want to embed and manage WPT yourself? Datira.ai is the ready-made SaaS platform built on WPT — upload data, build pivot reports, share with your team, all in the browser. Free tier available.