Skip to content

fix: outreach A/B variants display and thread linking#731

Merged
bokelley merged 3 commits into
mainfrom
bokelley/outreach-ab-data
Jan 12, 2026
Merged

fix: outreach A/B variants display and thread linking#731
bokelley merged 3 commits into
mainfrom
bokelley/outreach-ab-data

Conversation

@bokelley

Copy link
Copy Markdown
Contributor

Summary

  • Fix BigInt/Number type mismatch causing outreach A/B variants to show no data on /admin/outreach
  • Add reusable thread widget for viewing conversation threads across admin pages
  • Link outreach messages to threads when users respond, enabling conversation tracking

Changes

  1. Fix variant stats matching (insights-db.ts): Convert PostgreSQL BigInt values to JavaScript Numbers so frontend comparison works correctly
  2. New thread widget (thread-widget.js, thread-widget.css): Reusable component with expandable inline display, caching, and lazy loading
  3. Link outreach to threads (bolt-app.ts, insights-db.ts): When a user responds to outreach and a thread is created, store the thread_id in member_outreach
  4. Update admin pages: Add thread viewing to admin-users.html (outreach history + recent conversations) and admin-outreach.html (history tab)

Test plan

  • Visit /admin/outreach and verify A/B variants table shows data with response rates
  • Check outreach history tab shows expandable thread widgets for conversations
  • Visit /admin/users/:id and verify outreach history shows thread links
  • Trigger a new outreach response and verify thread_id gets populated in member_outreach

🤖 Generated with Claude Code

bokelley and others added 3 commits January 12, 2026 12:59
PostgreSQL bigint values may be returned as strings in JavaScript.
Convert variant IDs and related numeric fields to proper JS numbers
so the frontend can correctly match variant stats with variants.

This fixes the A/B Variants tab showing no data due to type mismatch
in the comparison `s.variant_id === v.id` (string vs number).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Link outreach records to unified_threads when user responds to DM
- Add linkOutreachToThread() method to insights-db.ts
- Create reusable ThreadWidget (js/thread-widget.js, css/thread-widget.css)
  - Expandable inline thread viewer
  - Fetches from /api/admin/addie/threads/:id
  - Supports compact mode, timestamps, max messages
- Update admin-users.html to use thread widget:
  - Outreach history: expandable thread view per outreach
  - Recent conversations: expandable thread view per conversation
- Update admin-outreach.html history tab:
  - Add Thread column with expandable widget

This enables viewing full conversation context directly from
outreach history and user profiles without switching pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add XSS protection: validate/sanitize channel, threadId, containerId
- Add LRU cache eviction (max 50 entries) to prevent memory growth
- Add UUID validation for threadId in thread widget and linkOutreachToThread
- Add container ID validation (alphanumeric, hyphens, underscores)
- Add null checks in toggleExpand to prevent crashes on missing elements
- Escape thread_id in data attributes in admin-outreach.html
- Extract normalizeVariant() helper for consistent BigInt conversion
- Apply Number() conversion consistently to createVariant, getVariant, updateVariant

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@bokelley bokelley merged commit 63da0ac into main Jan 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant