Skip to content

Commit f1e2c86

Browse files
authored
add html
1 parent dbca3fc commit f1e2c86

1 file changed

Lines changed: 248 additions & 0 deletions

File tree

quantum_metric_schema.html

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
<!DOCTYPE html>
2+
<!--
3+
Quantum Metric Session Archive Schema Tree — Interactive Collapsible Visualization
4+
Source: Quantum Metric
5+
6+
HOW TO REFRESH SCHEMA DATA:
7+
1. Query BigQuery table metadata for `atz-data-ingest-prd.quantummetrics_prd.sessions_archive`
8+
using the MCP BigQuery tool (get_table_info) or bq CLI:
9+
sessions_archive
10+
2. Transform each Schema field into { name: "field_name (TYPE)", children: [...] } format.
11+
- For REPEATED fields, prefix type: "REPEATED RECORD", "REPEATED STRING", etc.
12+
- Omit children key for leaf (non-RECORD) fields.
13+
- Root node name: "sessions_archive"
14+
3. Replace the SCHEMA_DATA constant below with the new JSON object.
15+
4. Open this file directly in a browser (file:// or http://).
16+
-->
17+
<html lang="en">
18+
<head>
19+
<meta charset="UTF-8">
20+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
21+
<title>Quantum Metric — sessions_archive Schema</title>
22+
<style>
23+
/* Edward Tufte–inspired theme: high data-ink ratio, restrained palette */
24+
* { margin: 0; padding: 0; box-sizing: border-box; }
25+
body {
26+
font-family: 'ET Book', Palatino, 'Palatino Linotype', 'Book Antiqua', Georgia, serif;
27+
background: #fffff8;
28+
color: #111;
29+
display: flex;
30+
flex-direction: column;
31+
height: 100vh;
32+
overflow: hidden;
33+
}
34+
header {
35+
padding: 18px 28px 10px;
36+
border-bottom: 1px solid #ddd;
37+
flex-shrink: 0;
38+
}
39+
header h1 {
40+
font-size: 1.35rem;
41+
font-weight: 400;
42+
letter-spacing: 0.01em;
43+
color: #333;
44+
}
45+
header p {
46+
font-size: 0.82rem;
47+
color: #777;
48+
margin-top: 2px;
49+
}
50+
.help {
51+
font-size: 0.75rem;
52+
color: #999;
53+
padding: 6px 28px;
54+
border-bottom: 1px solid #eee;
55+
flex-shrink: 0;
56+
}
57+
.help kbd {
58+
background: #f0f0f0;
59+
border: 1px solid #ccc;
60+
border-radius: 3px;
61+
padding: 1px 4px;
62+
font-size: 0.72rem;
63+
font-family: monospace;
64+
}
65+
#chart {
66+
flex: 1;
67+
min-height: 0;
68+
}
69+
#fallback {
70+
display: none;
71+
padding: 40px;
72+
text-align: center;
73+
color: #b00;
74+
font-size: 1rem;
75+
}
76+
.stats {
77+
font-size: 0.72rem;
78+
color: #aaa;
79+
padding: 4px 28px;
80+
border-top: 1px solid #eee;
81+
text-align: right;
82+
flex-shrink: 0;
83+
}
84+
</style>
85+
</head>
86+
<body>
87+
88+
<header>
89+
<h1>Quantum Metric sessions_archive Schema</h1>
90+
<p>Quantum Metric — BigQuery Schema Tree</p>
91+
</header>
92+
<div class="help">
93+
<kbd>Click</kbd> node to expand / collapse &nbsp;·&nbsp;
94+
<kbd>Scroll</kbd> to zoom &nbsp;·&nbsp;
95+
<kbd>Drag</kbd> to pan &nbsp;·&nbsp;
96+
<kbd>Right-click</kbd> to reset view
97+
</div>
98+
<div id="chart"></div>
99+
<div id="fallback">Schema data is missing or invalid. See source comments for regeneration steps.</div>
100+
<div class="stats" id="stats"></div>
101+
102+
<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
103+
<script>
104+
(function () {
105+
'use strict';
106+
107+
// ── Embedded schema payload (see header comment for refresh instructions) ──
108+
var SCHEMA_DATA = {"name":"sessions_archive","children":[{"name":"id (INTEGER)"},{"name":"cookie (STRING)"},{"name":"ts (INTEGER)"},{"name":"day (INTEGER)"},{"name":"hour (INTEGER)"},{"name":"last_updated (INTEGER)"},{"name":"screen_width (INTEGER)"},{"name":"screen_height (INTEGER)"},{"name":"conversion_count (INTEGER)"},{"name":"conversion_value (INTEGER)"},{"name":"cart_value (INTEGER)"},{"name":"abn_segment (STRING)"},{"name":"engaged (BOOLEAN)"},{"name":"conn_rtt (STRING)"},{"name":"conn_eff_type (STRING)"},{"name":"conn_down (STRING)"},{"name":"exit_click_sel (STRING)"},{"name":"exit_click_text (STRING)"},{"name":"exit_url (STRING)"},{"name":"qm_version (STRING)"},{"name":"application_type (STRING)"},{"name":"replay_enabled (BOOLEAN)"},{"name":"user (RECORD)","children":[{"name":"id (INTEGER)"},{"name":"email (STRING)"},{"name":"login (STRING)"},{"name":"cookies (REPEATED STRING)"},{"name":"firstname (STRING)"},{"name":"lastname (STRING)"},{"name":"loyalty (INTEGER)"},{"name":"data (STRING)"},{"name":"created (INTEGER)"},{"name":"updated (INTEGER)"}]},{"name":"locale (RECORD)","children":[{"name":"ip (STRING)"},{"name":"country_iso_code (STRING)"},{"name":"region (STRING)"},{"name":"city (STRING)"},{"name":"lat (FLOAT)"},{"name":"lng (FLOAT)"},{"name":"encrypted_ip (STRING)"},{"name":"encrypt_key (STRING)"},{"name":"hashed_ip (STRING)"}]},{"name":"device (RECORD)","children":[{"name":"name (STRING)"},{"name":"type (STRING)"},{"name":"user_agent (STRING)"},{"name":"browser_name (STRING)"},{"name":"browser_major_ver (INTEGER)"}]},{"name":"os (RECORD)","children":[{"name":"id (INTEGER)"},{"name":"name (STRING)"},{"name":"type (STRING)"}]},{"name":"landing_url (RECORD)","children":[{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"query_params (STRING)"}]},{"name":"last_url (RECORD)","children":[{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"query_params (STRING)"}]},{"name":"referrer (RECORD)","children":[{"name":"category (STRING)"},{"name":"sub_category (STRING)"},{"name":"url (RECORD)","children":[{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"query_params (STRING)"}]}]},{"name":"first_referrer (RECORD)","children":[{"name":"category (STRING)"},{"name":"sub_category (STRING)"},{"name":"url (RECORD)","children":[{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"query_params (STRING)"}]}]},{"name":"replay_viewed (BOOLEAN)"},{"name":"partition_date (DATE)"},{"name":"hits (REPEATED RECORD)","children":[{"name":"id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"secure (BOOLEAN)"},{"name":"response_size (INTEGER)"},{"name":"dom_interactive (INTEGER)"},{"name":"dom_complete (INTEGER)"},{"name":"engaged_seconds (INTEGER)"},{"name":"fetch_start (INTEGER)"},{"name":"domain_lookup_start (INTEGER)"},{"name":"domain_lookup_end (INTEGER)"},{"name":"connect_start (INTEGER)"},{"name":"secure_connection_start (INTEGER)"},{"name":"connect_end (INTEGER)"},{"name":"redirect_start (INTEGER)"},{"name":"redirect_end (INTEGER)"},{"name":"request_start (INTEGER)"},{"name":"response_start (INTEGER)"},{"name":"response_end (INTEGER)"},{"name":"dom_content_loaded_event_start (INTEGER)"},{"name":"dom_content_loaded_event_end (INTEGER)"},{"name":"load_event_start (INTEGER)"},{"name":"load_event_end (INTEGER)"},{"name":"first_paint (INTEGER)"},{"name":"first_contentful_paint (INTEGER)"},{"name":"elements_count (INTEGER)"},{"name":"spa_transition_duration (INTEGER)"},{"name":"spa_transition_apis (INTEGER)"},{"name":"spa_transition_mutations (INTEGER)"},{"name":"largest_contentful_paint (FLOAT)"},{"name":"first_input_delay (FLOAT)"},{"name":"cumulative_layout_shift (FLOAT)"},{"name":"timing_origin (INTEGER)"},{"name":"encoded_body_size (INTEGER)"},{"name":"decoded_body_size (INTEGER)"},{"name":"transfer_size (INTEGER)"},{"name":"clicks (INTEGER)"},{"name":"mouse_hundredth_miles (INTEGER)"},{"name":"scroll_hundredth_miles (INTEGER)"},{"name":"chars_typed (INTEGER)"},{"name":"exit_click_sel (STRING)"},{"name":"exit_click_text (STRING)"},{"name":"exit_url (STRING)"},{"name":"application_version (STRING)"},{"name":"query_string (STRING)"},{"name":"fragment_identifier (STRING)"},{"name":"max_scroll (INTEGER)"},{"name":"attn_10 (INTEGER)"},{"name":"attn_20 (INTEGER)"},{"name":"attn_30 (INTEGER)"},{"name":"attn_40 (INTEGER)"},{"name":"attn_50 (INTEGER)"},{"name":"attn_60 (INTEGER)"},{"name":"attn_70 (INTEGER)"},{"name":"attn_80 (INTEGER)"},{"name":"attn_90 (INTEGER)"},{"name":"attn_100 (INTEGER)"},{"name":"url (RECORD)","children":[{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"query_params (STRING)"}]},{"name":"referrer (RECORD)","children":[{"name":"url (RECORD)","children":[{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"query_params (STRING)"}]}]},{"name":"window_start_height (INTEGER)"},{"name":"window_start_width (INTEGER)"},{"name":"title (STRING)"},{"name":"parent_id (INTEGER)"},{"name":"scroll_depth (INTEGER)"},{"name":"is_server_side (BOOLEAN)"},{"name":"html_hash (STRING)"},{"name":"inp_value (INTEGER)"},{"name":"inp_selector (STRING)"}]},{"name":"hits_event (REPEATED RECORD)","children":[{"name":"hit_ts (INTEGER)"},{"name":"hit_domain (STRING)"},{"name":"hit_path (STRING)"},{"name":"hit_id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"id (INTEGER)"},{"name":"event_id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"event (STRING)"},{"name":"value (STRING)"},{"name":"display_in_ui (BOOLEAN)"},{"name":"is_conversion (BOOLEAN)"},{"name":"is_error (BOOLEAN)"},{"name":"data (JSON)"},{"name":"is_server_side (BOOLEAN)"}]},{"name":"hits_ajax (REPEATED RECORD)","children":[{"name":"hit_ts (INTEGER)"},{"name":"hit_id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"day (INTEGER)"},{"name":"hour (INTEGER)"},{"name":"domain (STRING)"},{"name":"path (STRING)"},{"name":"response_server_ms (INTEGER)"},{"name":"response_size (INTEGER)"},{"name":"response_code (INTEGER)"},{"name":"is_server_side (BOOLEAN)"},{"name":"query_string (STRING)"}]},{"name":"hits_forms (REPEATED RECORD)","children":[{"name":"hit_ts (INTEGER)"},{"name":"hit_id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"hit_form_id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"day (INTEGER)"},{"name":"hour (INTEGER)"},{"name":"form_name_id (INTEGER)"},{"name":"form_name (STRING)"},{"name":"form_action_id (INTEGER)"},{"name":"form_action (STRING)"},{"name":"fill_time_s (INTEGER)"},{"name":"fields (REPEATED RECORD)","children":[{"name":"id (INTEGER)"},{"name":"hit_id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"hit_form_id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"day (INTEGER)"},{"name":"hour (INTEGER)"},{"name":"field_name_id (INTEGER)"},{"name":"field_name (STRING)"},{"name":"fill_decaseconds (INTEGER)"},{"name":"filled_count (INTEGER)"},{"name":"is_filled (BOOLEAN)"},{"name":"is_drop_off (BOOLEAN)"},{"name":"value (STRING)"}]}]},{"name":"hits_click (REPEATED RECORD)","children":[{"name":"hit_ts (INTEGER)"},{"name":"hit_id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"selector (STRING)"},{"name":"parent_selector (STRING)"},{"name":"text (STRING)"},{"name":"time_to_click (INTEGER)"},{"name":"offsetx (INTEGER)"},{"name":"offsety (INTEGER)"}]},{"name":"hits_resources (REPEATED RECORD)","children":[{"name":"hit_ts (INTEGER)"},{"name":"hit_id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"id (INTEGER)"},{"name":"ts (INTEGER)"},{"name":"url (STRING)"},{"name":"connect_start (INTEGER)"},{"name":"connect_end (INTEGER)"},{"name":"domain_lookup_start (INTEGER)"},{"name":"domain_lookup_end (INTEGER)"},{"name":"decoded_body_size (INTEGER)"},{"name":"encoded_body_size (INTEGER)"},{"name":"fetch_start (INTEGER)"},{"name":"initiator_type (STRING)"},{"name":"next_hop_protocol (STRING)"},{"name":"redirect_start (INTEGER)"},{"name":"redirect_end (INTEGER)"},{"name":"request_start (INTEGER)"},{"name":"response_start (INTEGER)"},{"name":"response_end (INTEGER)"},{"name":"secure_connection_start (INTEGER)"},{"name":"transfer_size (INTEGER)"},{"name":"worker_start (INTEGER)"},{"name":"is_cached (BOOLEAN)"},{"name":"is_critical (BOOLEAN)"},{"name":"is_cross_origin (BOOLEAN)"},{"name":"is_async (BOOLEAN)"},{"name":"is_compressed (BOOLEAN)"},{"name":"server_timings (STRING)"}]},{"name":"timestamp (TIMESTAMP)"},{"name":"etl_batch (TIMESTAMP)"},{"name":"session_events (REPEATED RECORD)","children":[{"name":"ts (INTEGER)"},{"name":"id (INTEGER)"},{"name":"name (STRING)"},{"name":"source (STRING)"},{"name":"data (JSON)"}]},{"name":"is_server_side (BOOLEAN)"},{"name":"event_ids (REPEATED INTEGER)"},{"name":"has_errors (BOOLEAN)"},{"name":"surveys (REPEATED RECORD)","children":[{"name":"id (INTEGER)"},{"name":"session_id (INTEGER)"},{"name":"hit_id (INTEGER)"},{"name":"hit_ts (INTEGER)"},{"name":"hit_path (STRING)"},{"name":"hit_domain (STRING)"},{"name":"survey_id (STRING)"},{"name":"version (INTEGER)"},{"name":"response_id (STRING)"},{"name":"status (STRING)"},{"name":"answers (REPEATED RECORD)","children":[{"name":"id (INTEGER)"},{"name":"question_id (STRING)"},{"name":"response_text (STRING)"},{"name":"response_rating (INTEGER)"},{"name":"response_choices (REPEATED STRING)"},{"name":"sentiment (FLOAT)"},{"name":"categories (REPEATED STRING)"},{"name":"updated_ts (INTEGER)"},{"name":"labels (REPEATED STRING)"},{"name":"topics (REPEATED RECORD)","children":[{"name":"name (STRING)"},{"name":"subtopics (REPEATED STRING)"}]},{"name":"themes (REPEATED STRING)"},{"name":"question (STRING)"}]},{"name":"ts (INTEGER)"},{"name":"shown_ts (INTEGER)"},{"name":"started_ts (INTEGER)"},{"name":"last_updated (INTEGER)"},{"name":"survey (STRING)"}]}]};
109+
110+
// ── Validate payload ──
111+
if (!SCHEMA_DATA || !SCHEMA_DATA.children) {
112+
document.getElementById('chart').style.display = 'none';
113+
document.getElementById('fallback').style.display = 'block';
114+
return;
115+
}
116+
117+
// ── Compute stats ──
118+
function countNodes(node) {
119+
var c = 1;
120+
(node.children || []).forEach(function (ch) { c += countNodes(ch); });
121+
return c;
122+
}
123+
function maxDepth(node, d) {
124+
d = d || 0;
125+
if (!node.children) return d;
126+
return Math.max.apply(null, node.children.map(function (ch) { return maxDepth(ch, d + 1); }));
127+
}
128+
var totalNodes = countNodes(SCHEMA_DATA);
129+
var depth = maxDepth(SCHEMA_DATA, 0);
130+
document.getElementById('stats').textContent =
131+
totalNodes + ' fields · max depth ' + depth + ' · source: quantummetrics_prd.sessions_archive';
132+
133+
// ── Collapse nodes beyond initial depth ──
134+
var INITIAL_DEPTH = 1;
135+
function setCollapsed(node, currentDepth) {
136+
if (node.children && node.children.length) {
137+
if (currentDepth >= INITIAL_DEPTH) {
138+
node.collapsed = true;
139+
}
140+
node.children.forEach(function (ch) { setCollapsed(ch, currentDepth + 1); });
141+
}
142+
}
143+
setCollapsed(SCHEMA_DATA, 0);
144+
145+
// ── Style helpers ──
146+
// Color leaf vs record nodes differently for visual distinction
147+
function styleTree(node) {
148+
var isRecord = node.children && node.children.length > 0;
149+
node.itemStyle = { color: isRecord ? '#4a4a4a' : '#999' };
150+
node.label = {
151+
fontSize: isRecord ? 12 : 11,
152+
color: '#333',
153+
fontFamily: "'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace"
154+
};
155+
if (node.children) {
156+
node.children.forEach(styleTree);
157+
}
158+
}
159+
styleTree(SCHEMA_DATA);
160+
// Root gets special treatment
161+
SCHEMA_DATA.itemStyle = { color: '#111', borderWidth: 2 };
162+
SCHEMA_DATA.label = {
163+
fontSize: 14,
164+
fontWeight: 'bold',
165+
color: '#111',
166+
fontFamily: "'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace"
167+
};
168+
169+
// ── Init ECharts ──
170+
var chartDom = document.getElementById('chart');
171+
var chart = echarts.init(chartDom);
172+
173+
var option = {
174+
tooltip: {
175+
trigger: 'item',
176+
triggerOn: 'mousemove',
177+
formatter: function (params) {
178+
var d = params.data;
179+
var parts = d.name.match(/^(.+?)\s*\((.+)\)$/);
180+
if (parts) {
181+
var childCount = d.children ? d.children.length : 0;
182+
var tip = '<b>' + parts[1] + '</b><br/>Type: ' + parts[2];
183+
if (childCount > 0) tip += '<br/>Children: ' + childCount;
184+
return tip;
185+
}
186+
return '<b>' + d.name + '</b>';
187+
},
188+
backgroundColor: '#fffff8',
189+
borderColor: '#ccc',
190+
textStyle: { color: '#333', fontFamily: 'monospace', fontSize: 12 }
191+
},
192+
series: [{
193+
type: 'tree',
194+
data: [SCHEMA_DATA],
195+
orient: 'LR',
196+
top: 20,
197+
bottom: 20,
198+
left: 160,
199+
right: 260,
200+
symbolSize: 7,
201+
edgeShape: 'polyline',
202+
edgeForkPosition: '63%',
203+
initialTreeDepth: -1, // we control collapse state manually
204+
lineStyle: {
205+
color: '#ccc',
206+
width: 1
207+
},
208+
label: {
209+
position: 'left',
210+
verticalAlign: 'middle',
211+
align: 'right',
212+
fontSize: 11,
213+
fontFamily: "'SF Mono', 'Menlo', 'Monaco', 'Consolas', monospace",
214+
color: '#333'
215+
},
216+
leaves: {
217+
label: {
218+
position: 'right',
219+
verticalAlign: 'middle',
220+
align: 'left'
221+
}
222+
},
223+
expandAndCollapse: true,
224+
animationDuration: 400,
225+
animationDurationUpdate: 400,
226+
roam: true,
227+
scaleLimit: { min: 0.3, max: 3 }
228+
}]
229+
};
230+
231+
chart.setOption(option);
232+
233+
// ── Right-click to reset view ──
234+
chartDom.addEventListener('contextmenu', function (e) {
235+
e.preventDefault();
236+
chart.dispatchAction({ type: 'restore' });
237+
});
238+
239+
// ── Debounced resize ──
240+
var resizeTimer;
241+
window.addEventListener('resize', function () {
242+
clearTimeout(resizeTimer);
243+
resizeTimer = setTimeout(function () { chart.resize(); }, 150);
244+
});
245+
})();
246+
</script>
247+
</body>
248+
</html>

0 commit comments

Comments
 (0)