| Name | Last modified | Size | Description | |
|---|---|---|---|---|
| Parent Directory | - | |||
| CHANGELOG.md | 2026-03-31 21:01 | 4.0K | ||
| admin/ | 2026-03-28 16:07 | - | ||
| assets/ | 2026-03-28 16:07 | - | ||
| citcom-user-insights..> | 2026-03-31 21:01 | 7.6K | ||
| cui-debug.log | 2026-03-31 21:01 | 3.2K | ||
| freemius/ | 2026-03-31 21:03 | - | ||
| includes/ | 2026-03-31 21:04 | - | ||
| readme.txt | 2026-03-31 21:01 | 6.6K | ||
| server/ | 2026-03-28 16:13 | - | ||
| stubs/ | 2026-03-28 16:07 | - | ||
| uninstall.php | 2026-03-28 16:19 | 339 | ||
Comprehensive user behaviour analytics and CRM dashboard for WordPress & WooCommerce
CitCom. User Insights tracks every customer's journey — from anonymous first visit through to completed order — and surfaces that data in a clean admin interface built for sales and support teams.
The plugin records page views, sessions, device types, and WooCommerce order activity for every visitor, whether they are a logged-in user or a guest browsing without an account. Guest records are enriched automatically at checkout with billing information, and are merged into a registered user account when the guest logs in or creates an account at any point in the future.
All data is stored locally in your WordPress database — no external services or third-party analytics platforms required.
Every anonymous visitor receives a cui_guest_id cookie containing a 32-character random hex
string. The cookie is set with HttpOnly, SameSite: Lax, HTTPS-only on
secure sites, and a 1-year expiry.
A cui_session cookie tracks the current browsing session. Sessions expire after 30 minutes
of inactivity. Each session records the device type, browser, OS, IP address, and number of pages
viewed.
When a guest completes a WooCommerce checkout order, the plugin captures the billing name and email and stores them against the guest record. This works for both the classic WooCommerce shortcode checkout and the modern Checkout Block (Store API).
If a guest has checked out before using the same email address, the current session is merged into the existing canonical record. Page view and session counts are combined, and all visit/session rows are re-pointed to the canonical guest ID.
The guest tracking system handles three scenarios where a guest becomes a known user:
| Trigger | Hook | What Happens |
|---|---|---|
| Guest logs in to existing account | wp_login |
All visits/sessions transferred to user_id; guest cookie cleared;
historical email records also swept |
| Guest creates account at checkout | woocommerce_created_customer |
Same transfer logic; handles cases where wp_login is not fired by WC
internals |
| Guest checks out using a registered email | woocommerce_checkout_order_processed /
woocommerce_store_api_checkout_order_processed
|
Guest record enriched then immediately transferred to the matching user account; no login required |
All WooCommerce code is conditionally loaded — the plugin functions fully without WooCommerce installed. When WooCommerce is active, the following features become available:
Stats and recent orders on both the user profile page and the list table use a combined query that fetches:
customer_id = user_idbilling_email = user_email and
customer_id = 0
This prevents double-counting while ensuring the complete purchase history is always visible, regardless of how an order was placed.
wp_wc_customer_lookup analytics table (WooCommerce 3.9+)wc_get_orders() queries| Metric | Description |
|---|---|
| Lifetime Value | Total spend across all orders (logged-in + guest, formatted with currency) |
| Total Orders | Count of all completed, processing, or on-hold orders |
| Average Order Value | Lifetime value divided by total orders |
| Orders (Last 12 Months) | Orders within the past year |
| Last Order Date | Date of most recent order |
To avoid multiple database queries per row, WC stats for each user/guest row are fetched once and cached in a static array within the request. All three WC columns (orders, LTV, last order) share the same cached result.
Main page at User Insights in the WordPress admin menu. Displays all tracked registered
users and guest customers in a single sortable, filterable WP_List_Table.
| Column | Description |
|---|---|
| Name | Avatar + display name, linked to profile. "Guest" badge for unregistered visitors |
| Billing or account email (mailto link) | |
| Role | WordPress role or "Guest" |
| Last Seen | Human-readable time since last activity (e.g. "3 days ago") |
| Sessions | Total session count |
| Pages | Total page view count |
| Last Device | Device icon + browser + OS from most recent session |
| WC Orders | Orders in last 12 months (combined query) |
| Lifetime Value | Total spend, formatted with WooCommerce currency |
| Last Order | Date of most recent order |
Opened by clicking any registered user. Contains:
Opened by clicking any guest entry. Contains the same layout as the user profile with Activity and Orders
tabs. Orders are queried by billing email rather than customer_id.
| Setting | Description |
|---|---|
| Track guests | Enable or disable the guest tracking cookie entirely |
| Excluded roles | Checkbox list of user roles to exclude from tracking |
| Data retention | Automatically prune records older than N days (0 = keep forever) |
| Anonymise IPs | Mask the last octet of IPv4 or last 80 bits of IPv6 before storage |
All tables use the WordPress table prefix (default: wp_). Tables are created on plugin
activation and upgraded idempotently on each load via dbDelta().
wp_cui_page_visits| Column | Type | Description |
|---|---|---|
id |
BIGINT UNSIGNED | Primary key |
user_id |
BIGINT UNSIGNED | Logged-in user ID (NULL for guests) |
guest_id |
VARCHAR(64) | Guest token |
session_id |
BIGINT UNSIGNED | Session reference |
post_id |
BIGINT UNSIGNED | WordPress post/product ID |
post_type |
VARCHAR(50) | post, page, product, shop, product_category, etc. |
page_url |
VARCHAR(2048) | Full URL visited |
page_title |
VARCHAR(500) | Page title |
referrer |
VARCHAR(2048) | HTTP referrer |
visit_time |
DATETIME | When the visit occurred (UTC) |
time_on_page |
SMALLINT UNSIGNED | Seconds on page (updated on navigation away) |
wp_cui_sessions| Column | Type | Description |
|---|---|---|
id |
BIGINT UNSIGNED | Primary key |
user_id |
BIGINT UNSIGNED | Logged-in user ID (NULL for guests) |
guest_id |
VARCHAR(64) | Guest token |
session_token |
VARCHAR(64) | Unique session identifier (UNIQUE KEY) |
started_at |
DATETIME | Session start (UTC) |
last_activity |
DATETIME | Timestamp of last page view in session |
page_count |
SMALLINT UNSIGNED | Pages viewed during session |
device_type |
VARCHAR(20) | desktop / tablet / mobile |
browser |
VARCHAR(100) | Browser name |
browser_ver |
VARCHAR(20) | Browser major version |
os |
VARCHAR(100) | Operating system |
ip_address |
VARCHAR(45) | Client IP (may be anonymised) |
wp_cui_user_notes| Column | Type | Description |
|---|---|---|
id |
BIGINT UNSIGNED | Primary key |
user_id |
BIGINT UNSIGNED | Customer the note belongs to |
note |
TEXT | Note content (wp_kses_post sanitised) |
added_by |
BIGINT UNSIGNED | Admin user who created the note |
created_at |
DATETIME | Creation timestamp |
updated_at |
DATETIME | Last edited timestamp |
wp_cui_guests| Column | Type | Description |
|---|---|---|
id |
BIGINT UNSIGNED | Primary key |
guest_id |
VARCHAR(64) | Unique 32-char hex identifier (UNIQUE KEY) |
display_name |
VARCHAR(200) | Name extracted from WooCommerce billing |
email |
VARCHAR(200) | Email extracted from WooCommerce billing |
ip_address |
VARCHAR(45) | Client IP |
first_seen |
DATETIME | First visit timestamp |
last_seen |
DATETIME | Most recent activity timestamp |
page_count |
INT UNSIGNED | Cumulative page views |
session_count |
SMALLINT UNSIGNED | Cumulative sessions |
converted_user_id |
BIGINT UNSIGNED | User ID if converted to a registered account |
converted_at |
DATETIME | Conversion timestamp |
| Hook | Callback | Description |
|---|---|---|
plugins_loaded |
citcom_user_insights_init |
Bootstrap; loads classes, runs DB upgrade check |
send_headers |
CUI_Tracker::init_tracking |
Initialises session and guest cookie before output |
wp_enqueue_scripts |
CUI_Tracker::enqueue_tracker |
Enqueues frontend tracking script |
wp_ajax_cui_track_visit |
CUI_Tracker::ajax_track_visit |
Records a page view for logged-in users |
wp_ajax_nopriv_cui_track_visit |
CUI_Tracker::ajax_track_visit |
Records a page view for guests |
wp_ajax_cui_update_visit_time |
CUI_Tracker::ajax_update_visit_time |
Updates time-on-page on navigation away |
wp_ajax_nopriv_cui_update_visit_time |
CUI_Tracker::ajax_update_visit_time |
Same for guests |
wp_login |
CUI_Guest::transfer_on_login |
Transfers guest data to user account on login |
wp_login |
CUI_Tracker::record_last_login |
Saves last login timestamp to user meta |
woocommerce_checkout_order_processed |
CUI_Guest::maybe_enrich_from_order |
Enriches guest at classic shortcode checkout |
woocommerce_store_api_checkout_order_processed |
CUI_Guest::maybe_enrich_from_order_block |
Enriches guest at Checkout Block |
woocommerce_created_customer |
CUI_Guest::transfer_on_wc_registration |
Transfers data when WC creates account at checkout |
| Hook | Callback | Description |
|---|---|---|
admin_menu |
CUI_Admin::register_menu |
Registers the User Insights admin menu |
admin_enqueue_scripts |
CUI_Admin::enqueue_assets |
Enqueues admin CSS and JS |
admin_post_cui_save_settings |
CUI_Admin::save_settings |
Handles settings form submission |
admin_post_cui_clear_data |
CUI_Admin::clear_all_data |
Handles Danger Zone data wipe |
wp_ajax_cui_add_note |
CUI_Admin::ajax_add_note |
Creates a new CRM note |
wp_ajax_cui_update_note |
CUI_Admin::ajax_update_note |
Updates an existing CRM note |
wp_ajax_cui_delete_note |
CUI_Admin::ajax_delete_note |
Deletes a CRM note |
| Event | Callback | Description |
|---|---|---|
| Plugin activation | CUI_Database::install |
Creates all four database tables |
| Plugin uninstall | uninstall.php |
Drops tables and removes options (if configured) |
cui_prune_data (WP-Cron) |
CUI_Database::prune_old_data |
Removes records older than the retention setting |
wp_options)| Option Key | Type | Description |
|---|---|---|
cui_settings |
array | Master settings: tracking toggles, excluded roles, retention, IP anonymisation |
cui_db_version |
string | Installed schema version; used for idempotent upgrades |
cui_delete_data_on_uninstall |
bool | If true, all tables are dropped on plugin deletion |
wp_usermeta)| Meta Key | Description |
|---|---|
_cui_last_login |
Unix timestamp of the user's most recent login |
edit_users, manage_options) guard all admin pages and
actions$wpdb->prepare() with typed placeholders (%s,
%d)
sanitize_text_field, sanitize_email,
absint, wp_kses_post
esc_html, esc_attr, esc_url,
wp_kses_post
Required only for WC-specific features. Detected via class_exists('WooCommerce'). All WC
code is wrapped in CUI_WooCommerce::is_woocommerce_active() checks so the plugin degrades
gracefully when WooCommerce is not installed.
Required only for the wishlist tab. Detected via CUI_Wishlist::is_wishlist_active(). Reads
wishlist data from user meta keys woosw_key, woosw_keys, and the
woosw_list_{key} option entries created by that plugin.
1.1.0 2026-03-28 – WPConsent integration: visit
tracking gated behind statistics consent; script blocker support via
wpconsent_blocked_scripts filter; dynamic cookie name resolution via
wpconsent_frontend_js_data filter; wpconsent_consent_processed event listener
for mid-page consent; lazy session creation.
1.0.0 2026-03-01 – Initial release.