$wpdb->prefix . 'saddle_analytics_visitors', 'hits' => $wpdb->prefix . 'saddle_analytics_hits', 'crawlers' => $wpdb->prefix . 'saddle_analytics_crawlers', ); } public static function create_tables(): void { global $wpdb; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $t = self::tables(); $charset = $wpdb->get_charset_collate(); dbDelta( "CREATE TABLE {$t['visitors']} ( visitor_id char(32) NOT NULL, first_seen datetime NOT NULL, last_seen datetime NOT NULL, first_channel tinyint NOT NULL DEFAULT 0, first_referrer varchar(191) NULL, first_source varchar(100) NULL, first_medium varchar(100) NULL, first_campaign varchar(100) NULL, first_landing varchar(255) NULL, last_channel tinyint NOT NULL DEFAULT 0, last_referrer varchar(191) NULL, last_campaign varchar(100) NULL, country char(2) NULL, browser varchar(40) NULL, os varchar(40) NULL, device tinyint NULL, pageviews int unsigned NOT NULL DEFAULT 0, sessions int unsigned NOT NULL DEFAULT 0, PRIMARY KEY (visitor_id), KEY first_channel_seen (first_channel,first_seen), KEY last_seen (last_seen), KEY first_seen (first_seen) ) $charset;" ); dbDelta( "CREATE TABLE {$t['hits']} ( id bigint unsigned NOT NULL AUTO_INCREMENT, visitor_id char(32) NOT NULL, session_id char(32) NOT NULL, ts datetime NOT NULL, event_type tinyint NOT NULL DEFAULT 1, path varchar(255) NOT NULL DEFAULT '/', is_entry tinyint(1) NOT NULL DEFAULT 0, duration smallint unsigned NULL, target varchar(255) NULL, PRIMARY KEY (id), KEY ts_event (ts,event_type), KEY visitor (visitor_id), KEY session_ts (session_id,ts), KEY event_session (event_type,session_id,ts) ) $charset;" ); // Phase 18: one row per bot per UTC day — the AI-crawler report's rollup. // UNIQUE(day, bot) makes the write a single INSERT … ON DUPLICATE KEY. dbDelta( "CREATE TABLE {$t['crawlers']} ( id bigint unsigned NOT NULL AUTO_INCREMENT, day date NOT NULL, bot varchar(60) NOT NULL, purpose tinyint NOT NULL DEFAULT 0, hits int unsigned NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY day_bot (day,bot), KEY day (day) ) $charset;" ); } }