|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS companies ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
name TEXT NOT NULL, |
|
|
domain TEXT UNIQUE, |
|
|
industry TEXT, |
|
|
size TEXT, |
|
|
revenue TEXT, |
|
|
location TEXT, |
|
|
description TEXT, |
|
|
pain_points TEXT, |
|
|
website TEXT, |
|
|
linkedin_url TEXT, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_companies_domain ON companies(domain); |
|
|
CREATE INDEX idx_companies_industry ON companies(industry); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS contacts ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
company_id INTEGER, |
|
|
first_name TEXT, |
|
|
last_name TEXT, |
|
|
email TEXT UNIQUE NOT NULL, |
|
|
phone TEXT, |
|
|
job_title TEXT, |
|
|
department TEXT, |
|
|
seniority_level TEXT, |
|
|
linkedin_url TEXT, |
|
|
twitter_url TEXT, |
|
|
location TEXT, |
|
|
timezone TEXT, |
|
|
|
|
|
|
|
|
fit_score REAL DEFAULT 0.0, |
|
|
engagement_score REAL DEFAULT 0.0, |
|
|
intent_score REAL DEFAULT 0.0, |
|
|
overall_score REAL DEFAULT 0.0, |
|
|
|
|
|
|
|
|
status TEXT DEFAULT 'new', |
|
|
lifecycle_stage TEXT DEFAULT 'lead', |
|
|
|
|
|
|
|
|
source TEXT, |
|
|
first_contacted_at TIMESTAMP, |
|
|
last_contacted_at TIMESTAMP, |
|
|
last_activity_at TIMESTAMP, |
|
|
|
|
|
|
|
|
tags TEXT, |
|
|
notes TEXT, |
|
|
custom_fields TEXT, |
|
|
is_suppressed BOOLEAN DEFAULT 0, |
|
|
suppression_reason TEXT, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE SET NULL |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_contacts_email ON contacts(email); |
|
|
CREATE INDEX idx_contacts_company ON contacts(company_id); |
|
|
CREATE INDEX idx_contacts_status ON contacts(status); |
|
|
CREATE INDEX idx_contacts_lifecycle_stage ON contacts(lifecycle_stage); |
|
|
CREATE INDEX idx_contacts_overall_score ON contacts(overall_score); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS campaigns ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
name TEXT NOT NULL, |
|
|
description TEXT, |
|
|
status TEXT DEFAULT 'draft', |
|
|
|
|
|
|
|
|
target_industries TEXT, |
|
|
target_company_sizes TEXT, |
|
|
target_locations TEXT, |
|
|
target_job_titles TEXT, |
|
|
|
|
|
|
|
|
sequence_id INTEGER, |
|
|
goal_contacts INTEGER, |
|
|
goal_response_rate REAL, |
|
|
goal_meetings INTEGER, |
|
|
|
|
|
|
|
|
contacts_discovered INTEGER DEFAULT 0, |
|
|
contacts_enriched INTEGER DEFAULT 0, |
|
|
contacts_scored INTEGER DEFAULT 0, |
|
|
contacts_contacted INTEGER DEFAULT 0, |
|
|
contacts_responded INTEGER DEFAULT 0, |
|
|
meetings_booked INTEGER DEFAULT 0, |
|
|
|
|
|
|
|
|
started_at TIMESTAMP, |
|
|
completed_at TIMESTAMP, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
created_by TEXT, |
|
|
|
|
|
FOREIGN KEY (sequence_id) REFERENCES sequences(id) ON DELETE SET NULL |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_campaigns_status ON campaigns(status); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS campaign_contacts ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
campaign_id INTEGER NOT NULL, |
|
|
contact_id INTEGER NOT NULL, |
|
|
stage TEXT DEFAULT 'discovery', |
|
|
stage_updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
added_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
notes TEXT, |
|
|
|
|
|
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE CASCADE, |
|
|
FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE, |
|
|
UNIQUE(campaign_id, contact_id) |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_campaign_contacts_campaign ON campaign_contacts(campaign_id); |
|
|
CREATE INDEX idx_campaign_contacts_contact ON campaign_contacts(contact_id); |
|
|
CREATE INDEX idx_campaign_contacts_stage ON campaign_contacts(stage); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS sequences ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
name TEXT NOT NULL, |
|
|
description TEXT, |
|
|
category TEXT DEFAULT 'outbound', |
|
|
is_active BOOLEAN DEFAULT 1, |
|
|
is_template BOOLEAN DEFAULT 0, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
created_by TEXT |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS sequence_emails ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
sequence_id INTEGER NOT NULL, |
|
|
step_number INTEGER NOT NULL, |
|
|
wait_days INTEGER DEFAULT 0, |
|
|
subject TEXT NOT NULL, |
|
|
body TEXT NOT NULL, |
|
|
send_time_preference TEXT, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (sequence_id) REFERENCES sequences(id) ON DELETE CASCADE, |
|
|
UNIQUE(sequence_id, step_number) |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_sequence_emails_sequence ON sequence_emails(sequence_id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS email_activities ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
contact_id INTEGER NOT NULL, |
|
|
campaign_id INTEGER, |
|
|
sequence_email_id INTEGER, |
|
|
type TEXT NOT NULL, |
|
|
subject TEXT, |
|
|
preview TEXT, |
|
|
link_url TEXT, |
|
|
meta_data TEXT, |
|
|
occurred_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE, |
|
|
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE SET NULL, |
|
|
FOREIGN KEY (sequence_email_id) REFERENCES sequence_emails(id) ON DELETE SET NULL |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_email_activities_contact ON email_activities(contact_id); |
|
|
CREATE INDEX idx_email_activities_campaign ON email_activities(campaign_id); |
|
|
CREATE INDEX idx_email_activities_type ON email_activities(type); |
|
|
CREATE INDEX idx_email_activities_occurred ON email_activities(occurred_at); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS meetings ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
contact_id INTEGER NOT NULL, |
|
|
campaign_id INTEGER, |
|
|
title TEXT NOT NULL, |
|
|
description TEXT, |
|
|
scheduled_at TIMESTAMP NOT NULL, |
|
|
duration_minutes INTEGER DEFAULT 30, |
|
|
meeting_url TEXT, |
|
|
location TEXT, |
|
|
status TEXT DEFAULT 'scheduled', |
|
|
outcome TEXT, |
|
|
notes TEXT, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE, |
|
|
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE SET NULL |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_meetings_contact ON meetings(contact_id); |
|
|
CREATE INDEX idx_meetings_campaign ON meetings(campaign_id); |
|
|
CREATE INDEX idx_meetings_scheduled ON meetings(scheduled_at); |
|
|
CREATE INDEX idx_meetings_status ON meetings(status); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS activities ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
contact_id INTEGER, |
|
|
campaign_id INTEGER, |
|
|
meeting_id INTEGER, |
|
|
type TEXT NOT NULL, |
|
|
description TEXT, |
|
|
meta_data TEXT, |
|
|
performed_by TEXT, |
|
|
occurred_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (contact_id) REFERENCES contacts(id) ON DELETE CASCADE, |
|
|
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE SET NULL, |
|
|
FOREIGN KEY (meeting_id) REFERENCES meetings(id) ON DELETE SET NULL |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_activities_contact ON activities(contact_id); |
|
|
CREATE INDEX idx_activities_campaign ON activities(campaign_id); |
|
|
CREATE INDEX idx_activities_type ON activities(type); |
|
|
CREATE INDEX idx_activities_occurred ON activities(occurred_at); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS ab_tests ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
campaign_id INTEGER NOT NULL, |
|
|
sequence_id INTEGER NOT NULL, |
|
|
name TEXT NOT NULL, |
|
|
description TEXT, |
|
|
test_type TEXT NOT NULL, |
|
|
variant_a TEXT NOT NULL, |
|
|
variant_b TEXT NOT NULL, |
|
|
winner TEXT, |
|
|
status TEXT DEFAULT 'running', |
|
|
started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
completed_at TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE CASCADE, |
|
|
FOREIGN KEY (sequence_id) REFERENCES sequences(id) ON DELETE CASCADE |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS ab_test_results ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
ab_test_id INTEGER NOT NULL, |
|
|
variant TEXT NOT NULL, |
|
|
emails_sent INTEGER DEFAULT 0, |
|
|
emails_delivered INTEGER DEFAULT 0, |
|
|
emails_opened INTEGER DEFAULT 0, |
|
|
emails_clicked INTEGER DEFAULT 0, |
|
|
emails_replied INTEGER DEFAULT 0, |
|
|
meetings_booked INTEGER DEFAULT 0, |
|
|
|
|
|
FOREIGN KEY (ab_test_id) REFERENCES ab_tests(id) ON DELETE CASCADE, |
|
|
UNIQUE(ab_test_id, variant) |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS templates ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
name TEXT NOT NULL, |
|
|
category TEXT, |
|
|
subject TEXT NOT NULL, |
|
|
body TEXT NOT NULL, |
|
|
variables TEXT, |
|
|
is_active BOOLEAN DEFAULT 1, |
|
|
usage_count INTEGER DEFAULT 0, |
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS analytics_snapshots ( |
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, |
|
|
campaign_id INTEGER, |
|
|
date DATE NOT NULL, |
|
|
hour INTEGER, |
|
|
|
|
|
|
|
|
contacts_discovered INTEGER DEFAULT 0, |
|
|
contacts_enriched INTEGER DEFAULT 0, |
|
|
emails_sent INTEGER DEFAULT 0, |
|
|
emails_opened INTEGER DEFAULT 0, |
|
|
emails_clicked INTEGER DEFAULT 0, |
|
|
emails_replied INTEGER DEFAULT 0, |
|
|
meetings_booked INTEGER DEFAULT 0, |
|
|
|
|
|
|
|
|
open_rate REAL DEFAULT 0.0, |
|
|
click_rate REAL DEFAULT 0.0, |
|
|
response_rate REAL DEFAULT 0.0, |
|
|
meeting_rate REAL DEFAULT 0.0, |
|
|
|
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, |
|
|
|
|
|
FOREIGN KEY (campaign_id) REFERENCES campaigns(id) ON DELETE CASCADE, |
|
|
UNIQUE(campaign_id, date, hour) |
|
|
); |
|
|
|
|
|
CREATE INDEX idx_analytics_campaign ON analytics_snapshots(campaign_id); |
|
|
CREATE INDEX idx_analytics_date ON analytics_snapshots(date); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS settings ( |
|
|
key TEXT PRIMARY KEY, |
|
|
value TEXT NOT NULL, |
|
|
description TEXT, |
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP |
|
|
); |
|
|
|
|
|
|
|
|
INSERT OR IGNORE INTO settings (key, value, description) VALUES |
|
|
('company_name', 'Your Company', 'Company name for email footers'), |
|
|
('company_address', '123 Main St, City, State 12345', 'Physical address for CAN-SPAM compliance'), |
|
|
('sender_name', 'Sales Team', 'Default sender name for emails'), |
|
|
('sender_email', 'hello@example.com', 'Default sender email'), |
|
|
('daily_email_limit', '1000', 'Maximum emails to send per day'), |
|
|
('enable_tracking', '1', 'Enable email open and click tracking'), |
|
|
('auto_pause_on_low_score', '1', 'Automatically pause contacts with low engagement'), |
|
|
('min_engagement_score', '0.3', 'Minimum engagement score before auto-pause'); |
|
|
|