sample_data.sql

-- Sample Data Generator for Causal ROI Dashboard
-- Creates 100 paths with 7 days of realistic treatment/control data
-- Run this to test the dashboard before connecting real data sources

-- ============================================================================
-- SAMPLE NODES (signals, actions, outcomes)
-- ============================================================================

INSERT INTO `causal_roi.nodes` (node_id, node_type, label, props) VALUES
-- Signals
('signal_001', 'signal', 'High Intent Search', JSON '{"source": "google_ads", "priority": "high"}'),
('signal_002', 'signal', 'Email Open', JSON '{"source": "sendgrid", "priority": "medium"}'),
('signal_003', 'signal', 'Cart Abandon', JSON '{"source": "shopify", "priority": "high"}'),
('signal_004', 'signal', 'Product View', JSON '{"source": "web_analytics", "priority": "low"}'),
('signal_005', 'signal', 'Price Drop Alert', JSON '{"source": "pricing_engine", "priority": "high"}'),

-- Actions
('action_001', 'action', 'Send Promo Email', JSON '{"channel": "email", "cost_per": 0.05}'),
('action_002', 'action', 'Display Retargeting Ad', JSON '{"channel": "display", "cost_per": 2.5}'),
('action_003', 'action', 'Search Ad Bid Increase', JSON '{"channel": "search", "cost_per": 3.2}'),
('action_004', 'action', 'Push Notification', JSON '{"channel": "mobile", "cost_per": 0.02}'),
('action_005', 'action', 'SMS Reminder', JSON '{"channel": "sms", "cost_per": 0.15}'),

-- Outcomes
('outcome_001', 'outcome', 'Revenue', JSON '{"kpi": "revenue", "unit": "usd"}'),
('outcome_002', 'outcome', 'Conversion', JSON '{"kpi": "conversion", "unit": "count"}'),
('outcome_003', 'outcome', 'LTV', JSON '{"kpi": "ltv", "unit": "usd"}');

-- ============================================================================
-- SAMPLE EDGES (signal->action->outcome paths)
-- ============================================================================

INSERT INTO `causal_roi.edges` (edge_id, src_node_id, dst_node_id, edge_type, latest_delta_roi, latest_latency_ms, decay_weight, n_observations) VALUES
-- High-performing paths
('edge_s1_a1', 'signal_001', 'action_001', 'signal->action', 2.8, 1200, 0.92, 450),
('edge_a1_o1', 'action_001', 'outcome_001', 'action->outcome', 2.8, 86400000, 0.92, 450),

('edge_s3_a2', 'signal_003', 'action_002', 'signal->action', 3.2, 900, 0.95, 520),
('edge_a2_o1', 'action_002', 'outcome_001', 'action->outcome', 3.2, 172800000, 0.95, 520),

-- Medium-performing paths
('edge_s2_a1', 'signal_002', 'action_001', 'signal->action', 1.5, 2400, 0.78, 320),
('edge_s4_a3', 'signal_004', 'action_003', 'signal->action', 1.2, 3600, 0.65, 280),
('edge_a3_o1', 'action_003', 'outcome_001', 'action->outcome', 1.2, 259200000, 0.65, 280),

-- Low/negative-performing paths
('edge_s4_a4', 'signal_004', 'action_004', 'signal->action', -0.3, 1800, 0.45, 150),
('edge_a4_o1', 'action_004', 'outcome_001', 'action->outcome', -0.3, 86400000, 0.45, 150),

-- Mixed paths
('edge_s5_a5', 'signal_005', 'action_005', 'signal->action', 1.8, 1500, 0.82, 380),
('edge_a5_o1', 'action_005', 'outcome_001', 'action->outcome', 1.8, 43200000, 0.82, 380);

-- ============================================================================
-- SAMPLE PATHS (100 synthetic paths over 7 days)
-- ============================================================================

-- Generate path IDs and forecasts
DECLARE path_counter INT64 DEFAULT 1;
WHILE path_counter <= 100 DO
  INSERT INTO `causal_roi.events_forecast` (path_id, hypothesis_id, t0, features)
  VALUES (
    CONCAT('path_', LPAD(CAST(path_counter AS STRING), 4, '0')),
    CONCAT('hyp_', CAST(MOD(path_counter, 10) AS STRING)),
    TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL MOD(path_counter, 7) DAY),
    JSON '{"model_version": "v2.3", "confidence": 0.75}'
  );
  SET path_counter = path_counter + 1;
END WHILE;

-- ============================================================================
-- SAMPLE ACTIONS (varying spend levels)
-- ============================================================================

INSERT INTO `causal_roi.events_action` (path_id, action_id, channel, spend, t1, metadata)
SELECT 
  ef.path_id,
  CONCAT('act_', ef.path_id),
  CASE MOD(CAST(SUBSTR(ef.path_id, 6) AS INT64), 5)
    WHEN 0 THEN 'email'
    WHEN 1 THEN 'display'
    WHEN 2 THEN 'search'
    WHEN 3 THEN 'mobile'
    ELSE 'sms'
  END AS channel,
  -- Varying spend: $50-$5000
  50 + (RAND() * 4950) AS spend,
  TIMESTAMP_ADD(ef.t0, INTERVAL CAST(500 + RAND() * 3000 AS INT64) MILLISECOND) AS t1,
  JSON '{"campaign": "Q4_test", "creative": "variant_A"}'
FROM `causal_roi.events_forecast` ef;

-- ============================================================================
-- SAMPLE OUTCOMES (treatment + control with realistic uplift)
-- ============================================================================

-- Treatment outcomes (actual observed revenue)
INSERT INTO `causal_roi.events_outcome` (path_id, kpi, value, t2, cohort_id)
SELECT
  ea.path_id,
  'revenue' AS kpi,
  -- Revenue = spend * base_roi * random_multiplier
  ea.spend * (1.5 + (RAND() * 2)) * 
    CASE 
      WHEN ea.channel IN ('email', 'sms') THEN 1.3  -- higher ROI channels
      WHEN ea.channel = 'display' THEN 1.0
      ELSE 0.8
    END AS value,
  TIMESTAMP_ADD(ea.t1, INTERVAL 1 DAY) AS t2,
  'treatment' AS cohort_id
FROM `causal_roi.events_action` ea;

-- Control outcomes (counterfactual - lower revenue)
INSERT INTO `causal_roi.events_outcome` (path_id, kpi, value, t2, cohort_id)
SELECT
  ea.path_id,
  'revenue' AS kpi,
  -- Control revenue = treatment * 0.6-0.9 (simulate uplift)
  ea.spend * (1.5 + (RAND() * 2)) * 
    CASE 
      WHEN ea.channel IN ('email', 'sms') THEN 1.3
      WHEN ea.channel = 'display' THEN 1.0
      ELSE 0.8
    END * (0.6 + RAND() * 0.3) AS value,  -- control is 60-90% of treatment
  TIMESTAMP_ADD(ea.t1, INTERVAL 1 DAY) AS t2,
  CONCAT('control_geo_', CAST(MOD(CAST(SUBSTR(ea.path_id, 6) AS INT64), 3) AS STRING)) AS cohort_id
FROM `causal_roi.events_action` ea;

-- ============================================================================
-- SAMPLE ATTRIBUTION LINKS
-- ============================================================================

INSERT INTO `causal_roi.attribution_links` (path_id, method, weight, window_days)
SELECT 
  path_id,
  CASE MOD(CAST(SUBSTR(path_id, 6) AS INT64), 3)
    WHEN 0 THEN 'shapley'
    WHEN 1 THEN 'markov'
    ELSE 'geo_holdout'
  END AS method,
  0.3 + (RAND() * 0.7) AS weight,  -- 0.3 to 1.0
  7 AS window_days
FROM `causal_roi.events_forecast`;

-- ============================================================================
-- SAMPLE CONTROL COHORTS
-- ============================================================================

INSERT INTO `causal_roi.control_cohorts` (cohort_id, path_id, method, geo_region, quality_score)
SELECT 
  CONCAT('control_geo_', CAST(MOD(CAST(SUBSTR(ef.path_id, 6) AS INT64), 3) AS STRING)),
  ef.path_id,
  'geo_holdout' AS method,
  CASE MOD(CAST(SUBSTR(ef.path_id, 6) AS INT64), 3)
    WHEN 0 THEN 'US-CA'
    WHEN 1 THEN 'US-TX'
    ELSE 'US-NY'
  END AS geo_region,
  0.75 + (RAND() * 0.2) AS quality_score  -- 0.75 to 0.95
FROM `causal_roi.events_forecast` ef;

-- ============================================================================
-- VERIFY SAMPLE DATA
-- ============================================================================

-- Check row counts
SELECT 'events_forecast' AS table_name, COUNT(*) AS rows FROM `causal_roi.events_forecast`
UNION ALL
SELECT 'events_action', COUNT(*) FROM `causal_roi.events_action`
UNION ALL
SELECT 'events_outcome', COUNT(*) FROM `causal_roi.events_outcome`
UNION ALL
SELECT 'attribution_links', COUNT(*) FROM `causal_roi.attribution_links`
UNION ALL
SELECT 'nodes', COUNT(*) FROM `causal_roi.nodes`
UNION ALL
SELECT 'edges', COUNT(*) FROM `causal_roi.edges`;

-- Sample path check (should show treatment vs control)
SELECT 
  path_id,
  cohort_id,
  AVG(value) AS avg_revenue,
  COUNT(*) AS n_obs
FROM `causal_roi.events_outcome`
WHERE path_id = 'path_0001'
GROUP BY path_id, cohort_id;
← All docsView source on GitHub →