KB // DIALPAD ANALYTICS
MANAGER TREND VIEW
6 CHARTS · CHART.JS 4.4 DIALPAD STATS API v2
Knowledge Base · Dialpad Analytics
Dialpad
Manager Trend View
Complete reference for the Dialpad Manager Trend View — a call center analytics dashboard wired to the Dialpad Stats API v2. Covers six time-series charts, the three-job async fetch pattern, RFC-4180 CSV parsing, derived metric formulas, SLA thresholds, documented API limitations, and the full path from demo to live production.
6 CHARTS CHART.JS 4.4 DIALPAD STATS API v2 3-JOB ASYNC FETCH DEMO · LIVE · PRODUCTION MODES RFC-4180 CSV PARSER

The Dialpad Manager Trend View is a single-file HTML analytics dashboard for call center managers. It renders six time-series charts — call volume, ASA, abandonment rate, service level, AHT, and CSAT/utilization — across selectable 1, 7, 14, or 30-day ranges. Data comes from the Dialpad Stats API v2 via a three-job async fetch pattern, with a fully functional demo mode requiring no credentials.

This file is a sub-page of the parent platform shell. It loads ../nav.js for the site-wide navigation overlay. A missing nav.js produces a 404 in the browser console but does not break the dashboard — all charts, controls, and modes function fully without it.

Primary Use Cases
  • Morning Review: Manager scans 7D view for overnight volume, SL, and CSAT before shift briefing.
  • Intra-Day Monitoring: Live + Production Mode (5-min auto-refresh) tracks SLA compliance in real time.
  • QBR Prep: Switch to 30D range for portfolio-level trend screenshots for client reporting.
  • Agent Efficiency: CSAT + utilization split panel surfaces workload vs. quality patterns.
What It Replaces
  • Dialpad Analytics portal — requires portal login, no multi-metric view, no date range flexibility.
  • Manual CSV exports — the dashboard automates the POST-then-poll export pattern entirely.
  • Spreadsheet trend tracking — derived metrics (abandon rate, SL%, utilization) computed automatically.
  • Separate CSAT reports — CSAT fetched in the same cycle as call stats, rendered on the same time axis.
Three Operating Modes Demo: generated data, no API key, instant render. Live: real Dialpad API, key in rail, manual refresh. Production: live data with 5-minute auto-refresh via the Production toggle. All three use the same renderCharts(stats) pipeline — only the data source differs.

A single self-contained HTML file. No build step. No server-side component. All logic executes in the browser. The rendering pipeline is linear: data in → normalize → charts out.

Rendering Pipeline
1
DOMContentLoaded → loadData()
Checks MODE. If 'demo': calls genDemoData(DAYS) immediately and passes result to renderCharts(stats). If 'live': calls fetchLiveData(). API key is also restored from localStorage('dp_api_key') before this fires — if a saved key is found, MODE is pre-set to 'live'.
2
Three-Job Async Fetch (live mode)
fetchLiveData() issues three sequential POST /api/v2/stats jobs: stat_type=calls, stat_type=onduty, and stat_type=csat. Each job is polled via GET /api/v2/stats/{id} until the CSV is ready. Total wall time: approximately 60–90 seconds per full load.
3
normalizeStats(callsCSV, ondutyCSV, csatCSV)
All three CSV strings are parsed by the RFC-4180 parseCSV() function, merged into a dataByDate map keyed by YYYY-MM-DD, and all derived metrics are computed exactly once here. Returns a single normalized stats object — or null on empty input, which triggers demo fallback.
4
renderCharts(stats)
Consumes the normalized stats object. Each chart is created via mkC(id, type, data, opts) which destroys any existing chart at that canvas ID before creating a new one (prevents memory leaks on repeated refreshes). Rail stats, KPI health badges, and trend arrows all update in the same synchronous pass.
State Variables
VariableDefaultPurpose
CHARTS{}Registry of active Chart.js instances keyed by canvas ID. Used by mkC() to destroy before re-create.
MODE'demo'Current mode: 'demo' or 'live'. Controls branch taken in loadData().
DAYS7Range in days. Set by range buttons (1/7/14/30). Passed to genDemoData() and the API POST body.
PRODUCTIONfalseWhen true, auto-refresh runs every 5 minutes via _prodTimer interval handle.
TARGET_ID'off_1a2b'Dialpad target ID for the API POST body. Changed by the TARGET dropdown.
API_KEY'' or restoredDialpad API key. Set by saveKey(), persisted base64-encoded in localStorage.
_prodTimernullsetInterval handle for Production Mode. Cleared on mode exit to prevent ghost refreshes.

Two persistent chrome elements sit above the 2×3 chart grid: the Rail (48px) and the Status Bar (28px). Always visible regardless of range or mode.

Rail — Seven Live Stats
StatIDColorValueGood Direction
Svc Levelrb-slGREENAvg service level % over range↑ = green
ASA Avgrb-asaCYANAvg speed to answer in seconds↓ = green (inverted)
Abandon Raterb-abnORANGEAvg abandonment %↓ = green (inverted)
Calls (Nd)rb-volBLUETotal inbound call volume over range↑ = green
AHT Avgrb-ahtPURPLEAvg handle time in minutes↓ = green (inverted)
CSAT Avgrb-csatYELLOWAvg CSAT score (1–5)↑ = green
Agent Utilrb-utilGREENAvg agent utilization %↑ = green (target band 75–85%)
Rail Controls
RANGE buttons1D 7D 14D 30D — each calls setRange(days, btn). Keyboard shortcuts: 1, 2/7, 3, 4.
TARGET dropdownSelects Dialpad target. Sets TARGET_ID and TARGET_NAME, then calls loadData(). Replace demo values with real Dialpad callcenter IDs for live use.
MODE indicatorYellow pulsing dot = DEMO. Green solid = LIVE. Green solid + "PROD" label = Production Mode.
KEY inputPassword-masked. Clicking SET calls saveKey() — stores key as base64 in localStorage('dp_api_key'), sets MODE to live, triggers load. Key persists across page reloads.
Refresh buttonCalls loadData() immediately. Demo re-generates; live triggers a full three-job fetch.
Production buttonToggles PRODUCTION. When on: setInterval(loadData, 300000) (5 min). When off: clears interval via _prodTimer. Requires saved API key.
Status Bar
ElementWhat It Shows
✓ APIPOST /api/v2/stats → GET /api/v2/stats/{id} — confirms the active endpoint pattern
stat_type=callsAvailable fields: inbound, outbound, missed, abandoned, asa, aht, service_level
stat_type=ondutyAvailable fields: available, occupied, wrapup (agent duty hours)
stat_type=csatAvailable fields: response (1–5 survey score per row)
N/A FCR N/A Disconnect N/A ForecastPermanently unavailable — see Section 13 for full explanation
KPI badges (SL, ASA, ABN, UTIL, CSAT)Health-colored badge per KPI. Green (↑), yellow (◊), red (↓). Updated on every render.
fetch-statusText: "Ready" / "running…" (yellow) / "Demo data · Nd" (green) / error message (red)
last-fetchedTimestamp of last successful data load. Set by setLastFetched().
stat_type=calls  Call Volume — Stacked Bar

Canvas: c-vol  ·  Panel: cp-vol  ·  Grid: col 1 row 1 (largest panel)  ·  Click to open Detail Pane

Stacked bar chart showing daily call counts by outcome across the selected range. Header displays total period volume. Clicking the panel opens the Detail Pane with full API field reference and the exact POST body used.

DatasetAPI FieldColorNotes
Inboundinbound_callsCYANTotal inbound calls. Base of stack.
Outboundoutbound_callsGREENAgent-placed outbound calls.
MissedmissedORANGERang but not answered, not queued.
AbandonedabandonedREDEntered queue but hung up before answer. Used in abandon rate formula.
Today Data Refresh Rate Today's stats in Dialpad refresh approximately every 30 minutes. Historical completed days refresh every 4–5 hours. The dashboard always uses is_today: false for stable completed-day data only.
asa field  Avg Speed to Answer — Filled Line

Canvas: c-asa  ·  Panel: cp-asa  ·  SLA target line at 20 seconds (yellow dashed)

API fieldasa from stat_type=calls. Dialpad exports ASA in minutes. Normalization multiplies × 60 for seconds display: d.asa_s = parseFloat(r.asa) * 60. Do not re-convert.
Formula (Dialpad-side)ASA = (date_connected – earliest of date_queued or date_first_rang) ÷ answered_calls. Computed by Dialpad before export — not derived client-side.
Target scopeAvailable for callcenter, department, office, and individual user targets.
Unit Conversion Critical The asa field is in minutes, not seconds. The × 60 in normalizeStats() is essential. A missing multiply produces ASA of 0.2–0.5, making every day appear green when it may be over threshold.
abandoned ÷ inbound  Abandonment Rate — Filled Line

Canvas: c-abn  ·  Panel: cp-abn  ·  SLA target line at 5% (red dashed)

Derived metric — not a direct API field. Header value and color code red/orange/green vs. the 5% SLA ceiling.

FormulaabandonRate = abandoned / inbound_calls × 100. Computed per date in normalizeStats(). Returns null if inbound_calls = 0 (chart shows gap).
short_abandonedAlso available in the export — calls abandoned within a configurable short-abandon threshold (typically <5s). Useful for filtering accidental disconnects. Not currently displayed.
open_abandoned_callsAvailable in the export — calls still showing as unresolved abandons. Not currently displayed.
CC targets only  Service Level % — Filled Line

Canvas: c-sl  ·  Panel: cp-sl  ·  SLA target line at 80% (green dashed)

API fieldservice_level — a count of calls meeting the SLA threshold, not a percentage. Dashboard computes: service_level / answered × 100.
Target restrictionContact Center and Department targets only. Not available for individual user or mainline office targets. Using this metric on a non-CC target returns null/zero for every date.
SLA standard80/20 rule: 80% of calls answered within 20 seconds. The 20-second threshold is set in Dialpad's Contact Center configuration, not in this dashboard.
Contact Center Targets Only If TARGET is a department or office, Service Level and AHT charts show all-null gap lines. No error is thrown — the SLA reference line still renders. Switch to a callcenter target type.
aht field · CC only  Avg Handle Time — Bar Chart

Canvas: c-aht  ·  Panel: cp-aht  ·  SLA band: 5–7 min (two purple dashed lines)

API fieldAHT (uppercase) or aht. Normalization checks both: r.AHT || r.aht. Returned in minutes. Contact Center targets only.
Bar color logicPer-bar: v < 5 → cyan (too fast), v ≤ 7 → purple (on-target), v > 7 → red (too slow). Null values = transparent.
Related fieldswrapup_duration, avg_wrapup_duration, talk_time — available in the export but not currently displayed.
csat + onduty  CSAT & Agent Util — Split Panel

Canvas IDs: c-csat (left) + c-util (right)  ·  Panel: cp-csat  ·  Click to open Detail Pane

The sixth panel is a CSS grid split into two equal halves inside the canvas parent div. Left: CSAT bar chart (1–5 scale). Right: agent utilization filled line chart.

CSAT — Left Half
Sourcestat_type=csat with export_type=records. Each CSV row is one survey response. The response field = score (1–5).
AggregationResponses grouped by date in csatByDate, then averaged per day in normalizeStats(). Days with no responses = null (chart gap).
Bar colors≥4.5 → green / ≥4.0 → yellow / else → orange. SLA target line at 4.5 (yellow dashed).
Agent Utilization — Right Half
Sourcestat_type=onduty. Fields: available, occupied, wrapup (all in agent-hours).
Formulautilization = (occupied + wrapup) / (available + occupied + wrapup) × 100. Returns null if total = 0.
SLA bandTwo purple dashed lines at 75% and 85%. Below 75% = underutilized. Above 85% = burnout/overflow risk. Target: 75–85%.

The dashboard uses the Dialpad Stats API v2 — an async job-pattern API. You POST a job, receive a job ID, wait, then poll GET until the CSV is ready. There is no synchronous endpoint that returns data immediately.

Endpoints
MethodEndpointPurpose
POSThttps://dialpad.com/api/v2/statsInitiate a stats export job. Returns { id: "job_xxx" }. Three calls per load cycle.
GEThttps://dialpad.com/api/v2/stats/{id}Poll for job completion. Returns CSV directly (content-type text/csv) or a JSON status with url pointing to the CSV download.
POST Body Parameters
JSON — POST /api/v2/stats
{
  "export_type":   "stats",           // "stats" for daily aggregates; "records" for CSAT individual rows
  "stat_type":    "calls",           // "calls" | "onduty" | "csat"
  "target_type":  "callcenter",      // "callcenter" | "department" | "office" | "user"
  "target_id":    "off_1a2b",        // Dialpad callcenter / office / user ID
  "timezone":     "America/Chicago", // IANA timezone — affects day boundary calculation
  "is_today":     false,             // false = completed historical days; true = includes live today (~30min refresh)
  "days_ago_start": 7,               // How many days back to start — DAYS state variable
  "days_ago_end":   0                // 0 = through yesterday; 1 = exclude yesterday
}
CSAT uses export_type=records, not stats The CSAT POST uses "export_type": "records" (individual survey rows). Using "stats" for CSAT returns an aggregate — not per-row responses — and cannot be averaged per day. The dashboard correctly uses records for CSAT only.
Authentication
HeaderAuthorization: Bearer <api_key>. Key stored in localStorage('dp_api_key') as base64. Transmitted only to dialpad.com.
Key formatDialpad API keys follow pattern dp_live_xxxxxxxxxxxx. Generated in Dialpad Admin under API Settings.
CORSDialpad does not allow browser-side CORS for the stats endpoint. Direct fetch() from a browser will be blocked. A proxy server is required for production. See Section 17.

Implemented in fetchLiveData() and pollStats(id, headers, base, waitStep, getStep). All fetch steps are visualized in the Fetch Overlay modal with a progress bar.

Three-Job Sequence
A
POST /api/v2/stats (stat_type=calls)
Initiates calls export job. Requires Authorization and Content-Type: application/json. Returns { id: "job_xxx" }. Throws on non-OK response or missing ID.
B
Wait 18 seconds, then poll GET /api/v2/stats/{id}
Dialpad docs recommend waiting 15–20 seconds before first poll. Dashboard waits exactly 18s via await wait(18000). Polls every 8 seconds, up to 12 attempts. On each GET: checks content-type for CSV, or checks JSON for status: "done" and a url field to fetch the CSV from.
C
POST + poll for stat_type=onduty
Same async pattern. Returns agent duty status hours per day (available, occupied, wrapup). Separate job ID.
D
POST + poll for stat_type=csat (export_type=records)
Same async pattern. Returns individual CSAT survey responses. One CSV row per submitted survey.
E
normalizeStats() → renderCharts()
All three CSVs parsed and merged. Derived metrics computed. Charts rendered. On any fetch error, demo data is rendered as a fallback and a warning toast is shown — charts never go blank.
Expected Total Load Time A full live load for a 7-day range takes approximately 60–90 seconds: 18s initial wait × 3 jobs = 54s minimum, plus poll cycles and CSV download. The Fetch Overlay displays step-by-step progress during this time.
parseCSV() — RFC-4180 Tokenizer

A custom RFC-4180 compliant tokenizer that handles quoted fields, embedded commas inside quoted fields, escaped quotes (""), Windows (\r\n) and Unix (\n) line endings. Returns an array of objects keyed by the header row. Returns empty array on blank input. Replaces a naive split(',') which would corrupt fields containing commas (e.g. client names, issue descriptions).

normalizeStats() — Single Derivation Layer

Merges all three CSV datasets into one dataByDate map keyed by YYYY-MM-DD. All derived metrics are computed exactly once here — renderCharts() only consumes pre-computed values.

Derived MetricFormulaReturns Null When
Service Level %service_level / answered × 100answered = 0
Abandon Rate %abandoned / inbound_calls × 100inbound_calls = 0
ASA (seconds)asa (minutes) × 60asa field missing
Agent Utilization %(occupied + wrapup) / (avail + occ + wru) × 100total hours = 0
CSAT daily avgavg(response) per date groupno responses that day
Null = Chart Gap, Not Zero Null values render as gaps in line charts (no interpolation, spanGaps: true) and as transparent bars in bar charts. This correctly communicates missing data rather than falsely showing zero performance.
Date Handling

Dialpad exports include a date, date_started, or Date field — normalization checks all three. Dates are extracted as YYYY-MM-DD by splitting on T. The final dataset is sorted ascending using Object.keys(dataByDate).sort().

The following metrics are displayed as N/A in the status bar because they are not buildable from the Dialpad Stats API v2 in any form. These limitations are also documented inside the Detail Pane for each chart.

Four metrics cannot be built from any current Dialpad export No workaround exists within the Stats API. An external data source (CRM, WFM platform, call recordings platform) would be required.
MetricWhy Not Available
FCR (First Call Resolution)No First Call Resolution field in any Dialpad stats or records export. FCR requires call-outcome tagging at the agent level, which Dialpad does not expose via API.
Disconnect RateNo mid-call drop metric. API tracks pre-answer abandonment and unanswered, but not calls that dropped during active conversation.
Forecast AccuracyDialpad provides no forecast vs. actual comparison. Workforce management forecasting data is not part of the Stats API schema.
Escalation RateOnly transfer counts (answered_transferred, transferred_out) are available. These are raw transfer counts — there is no flag to distinguish a warm transfer from an escalation.
Scope Restrictions
  • Service Level and AHT: Contact Center targets (target_type=callcenter) only. Null for department, office, and user targets.
  • CSAT: Requires Dialpad's CSAT feature enabled on the account. Without it, the csat export returns an empty CSV.
  • Today data: Refreshes ~30 min in Dialpad. Use is_today: false for stable completed-day data.
  • Large ranges: Ranges above 90 days may experience significantly longer job processing or timeouts. Not documented by Dialpad; observed behavior.
  • CORS: Direct browser requests to the Dialpad Stats API are blocked. A proxy is required for production. See Section 17.

Both genDemoData() and normalizeStats() produce the same stats object. renderCharts() consumes only this shape and does not know or care where data originated.

JavaScript — stats object shape
{
  dates:   ['YYYY-MM-DD', ...],     // N dates ascending — all chart x-axes

  calls: {
    inbound:  [number|null],  // inbound_calls per day
    outbound: [number|null],  // outbound_calls per day
    missed:   [number|null],  // missed calls per day
    abandoned:[number|null],  // abandoned calls per day
    answered: [number|null],  // answered calls per day (used in SL% formula)
    aht:      [number|null]   // avg handle time in minutes (CC targets only)
  },

  service: {
    serviceLevel: [number|null], // % — pre-computed: service_level / answered × 100
    asa:          [number|null], // seconds — pre-computed: asa_minutes × 60
    abandonRate:  [number|null]  // % — pre-computed: abandoned / inbound × 100
  },

  agents: {
    available:   [number|null], // agent-hours available
    occupied:    [number|null], // agent-hours on calls
    wrapup:      [number|null], // agent-hours in post-call wrap-up
    utilization: [number|null]  // % — pre-computed: (occ+wru) / total × 100
  },

  quality: {
    csat: [number|null]         // 1–5 avg per day — pre-computed from survey records
  }
}

All thresholds are hard-coded in renderCharts(). To change a threshold, update both the slaLine() value and the corresponding kpiBadge threshold array.

MetricGreen (OK)Yellow (Warn)Red (Crit)Reference Line(s)
Service Level≥ 80%70–79%< 70%80% green dashed
ASA< 20s20–30s> 30s20s yellow dashed
Abandon Rate< 3%3–5%> 5%5% red dashed
AHT5–7 min7–9 min<5 or >9 min5m + 7m purple dashed
CSAT≥ 4.5/54.0–4.49< 4.04.5 yellow dashed
Agent Util75–85%60–74%<60% or >85%75% + 85% purple dashed
SLA Reference Lines Are Plugin-Free Horizontal reference lines are Chart.js datasets with type:'line', pointRadius:0, and borderDash set. The slaLine(labels, val, color, dashes) helper generates them. No Chart.js Annotation plugin dependency.

The dashboard ships in demo mode. Data is generated by genDemoData(DAYS) using bounded Math.random() ranges. Weekend days produce ~40% lower call volumes. Every demo refresh regenerates all data — no persistence between refreshes.

Demo Behavior
  • No API calls are made in demo mode. The Dialpad API is never contacted.
  • Charts populate instantly — no fetch overlay, no wait period.
  • Weekend dips simulateddt.getDay()%6===0 uses 0.4× base multiplier.
  • ±20% daily variability produces realistic trend shapes, not flat lines.
  • CSAT null days occur — not every demo day generates a CSAT response, mirroring real low-survey-volume days.
Transitioning to Live Mode
1
Enter Dialpad API key in the rail
Type or paste key in the KEY input, click SET ▶. Saved to localStorage('dp_api_key') as base64. MODE switches to live and a data load fires automatically.
2
Deploy a CORS proxy
Dialpad blocks direct browser requests. Deploy an Azure Function, Cloudflare Worker, or Express endpoint that forwards POST /api/v2/stats and GET /api/v2/stats/{id} with the Authorization: Bearer header injected server-side. Update var base in fetchLiveData() to your proxy URL.
3
Replace demo TARGET_IDs
Update the TARGET dropdown <option value="..."> values with real Dialpad callcenter or office IDs. Update display names to match your clients.
4
Set correct timezone
Update "timezone": "America/Chicago" in the POST body to the IANA timezone of your call center. This controls day boundary calculations.
5
Enable Production Mode for continuous monitoring
Click ▶ Production in the rail — requires a saved API key. 5-minute auto-refresh via setInterval. Toggle off before leaving the page to clear the interval handle.
6
Remove KTC nav bar (if standalone deployment)
Delete #ktc-demo-bar div and its CSS block. Remove body { padding-top: 36px !important; } override. Ensure nav.js is accessible at ../nav.js — or update the script src to an absolute URL. A missing nav.js only affects site navigation, not the dashboard itself.

All items below activate when proxy is live. Features in demo mode today that require proxy to become functional are noted.

  • Deploy proxy server — Azure Function, Cloudflare Worker, or Express. Must forward POST /api/v2/stats and GET /api/v2/stats/{id} to Dialpad with Authorization: Bearer injected server-side.
  • Update base variable — In fetchLiveData(), change var base = 'https://dialpad.com/api/v2/' to your proxy base URL (e.g. '/api/proxy/dialpad/').
  • Move API key server-side — For shared kiosk/wall displays, store the key as an environment variable in the proxy. Remove the KEY input from the rail and let the proxy inject auth headers silently.
  • Replace TARGET_IDs — Update all <option value="..."> values and display names with real Dialpad callcenter / office IDs.
  • Set correct timezone — Update "timezone" in POST body to match each target's operational timezone.
  • Verify CSAT feature enabled — Confirm in Dialpad Admin that CSAT surveys are enabled for the target. Without this, the csat export is empty and CSAT chart shows all gaps.
  • Test full async fetch cycle — Run a live load and observe the Fetch Overlay. All steps A–H should complete with green checkmarks. Step C/E/G timeout = increase attempts or reduce DAYS range.
  • Test Production Mode — Enable Production, let it run 2 cycles (10 min). Verify 5-min interval fires, charts update, interval clears cleanly on toggle-off.
  • Remove demo KTC bar — Delete #ktc-demo-bar div and associated CSS for standalone deployment.
Common Issues
Charts show all dashes on loadExpected before loadData() completes first render. If dashes persist after toast appears, open console — likely Chart.js CDN failed to load.
Service Level / AHT always null gapsThese fields are Contact Center targets only. Switch TARGET to a target_type=callcenter target. Department and office targets will never populate these charts.
ASA shows 0.2–0.5 instead of 12–32The × 60 conversion in normalizeStats() was removed. Restore: d.asa_s = parseFloat(r.asa || 0) * 60. Dialpad exports ASA in minutes.
Live fetch times out at step C/E/GJob exceeded 12 poll attempts × 8s after 18s initial wait (~114s total). Reduce DAYS range or increase the attempt loop limit in pollStats().
CORS error on live fetchExpected without a proxy. Direct browser requests to dialpad.com are blocked. Deploy a proxy and update base in fetchLiveData(). See Section 17.
CSAT chart always emptyEither: CSAT not enabled in Dialpad Admin, or the csat POST is using export_type: "stats" instead of "records", or no surveys submitted in range.
Production Mode gone after page reload_prodTimer is an in-memory handle — does not persist across reloads. Re-enable Production Mode manually after reload.
API key visible via dev toolsKey is base64 in localStorage — not encrypted. On shared kiosk displays, move the key server-side to the proxy and remove the KEY input from the UI.
404 for nav.js in browser consoleDeploy this file where ../nav.js resolves, or update the script src to an absolute URL. Dashboard functions fully without nav.js — it only drives the site navigation overlay.
Memory leak on long wall sessionsmkC() calls chart.destroy() before recreating. If you add custom charts outside mkC(), call destroy() manually. Long sessions (8+ hours) without this accumulate canvas memory.
Customization Quick Reference
What to ChangeWhereHow
Date range optionsRange buttons in rail HTMLAdd <button class="range-btn" onclick="setRange(N,this)">ND</button>
Target offices / call centers<select id="target-sel">Replace demo off_xyyy option values with real Dialpad target IDs
TimezonefetchLiveData()body objectChange "timezone": "America/Chicago" to your IANA timezone
SLA thresholdsrenderCharts()Update both slaLine() value and the kpiBadge threshold array for each metric
Production auto-refresh intervaltoggleProduction()Change 5 * 60 * 1000 to desired milliseconds
Poll wait / retry timingpollStats()Change await wait(18000) (initial) and await wait(8000) (retry interval)
Chart color palette:root { } CSS blockUpdate --green, --accent, --red, --pur, --yellow
KTC nav bar#ktc-demo-bar div + style blockRemove entire div and associated CSS for standalone deployment
KB // DIALPAD ANALYTICS · MANAGER TREND VIEW 6 CHARTS · CHART.JS 4.4 · STATS API v2 · 3-JOB ASYNC FETCH