Skip to content

October 2025 - Visitor Profiling & Production Launch

Context

First production month. With infrastructure ready from September, October marked the transition to production with real client traffic. Key insight: understanding WHO is visiting is as important as WHAT they ask.

Status: Production (first month with real traffic and metrics)

Active clients: AB Tasty, Pennylane (accounting SaaS), Skaleet (banking SaaS), Skello (HR SaaS)

Key Business Metrics Tracked: 1. Initial Engagement Rate: % of visitors who interact with widget 2. Conversation Depth: Average number of turns per conversation 3. Conversion Rate: % of conversations leading to demo/email capture

Technical Challenge

Primary Problems: 1. Visitor identification: No way to know company/context of website visitors 2. Widget race conditions: Multiple useEffect hooks competing when analytics ready 3. CTA tracking unreliable: Events lost during page navigation 4. Form detection incomplete: Missing multi-step form support

Business Context: Without visitor identification, all conversations treated equally. Need to prioritize enterprise visitors and personalize responses.

Metrics-Driven Insight: September data showed technical questions convert 3x better than general questions - need to identify visitor intent and company context.


Hypothesis 1: Visitor Profile System with LLM Inference

"Combining IP enrichment with LLM-based inference from conversation content will provide comprehensive visitor profiles."

Development Work

Technical Challenge: We had no context about WHO was visiting. Enterprise visitors from target accounts were treated the same as anonymous browsers.

Architecture:

Visitor → IP Enrichment → VisitorProfile (partial)
        Conversation → LLM Inference → VisitorProfile (complete)
                    Merge profiles with conflict resolution

Key Innovation: Profile merging algorithm that handles conflicts between enrichment data and LLM inference:

def merge_visitor_profiles(left: VisitorProfile, right: VisitorProfile) -> VisitorProfile:
    """Intelligent merge with priority rules:
    - Prefer non-'unknown' values
    - Preserve 'completed' enrichment status over 'pending'
    - Union feature lists
    - Smart sector/sub-sector merging
    """

Implementation: - Visitor profiling system with LLM-based inference for sector/role detection - Integration with enrichment pipeline (initial single-source approach) - Profile persistence across sessions

Testing & Validation

Method: Integration tests + production validation - Created test dataset with known visitor profiles - Validated inference accuracy against manual labels

Results

Source Coverage Accuracy
IP Enrichment Only 35% High
LLM Inference Only 90% Medium
Combined (Merged) 95% High

Business Impact: | Metric | Before | After | |--------|--------|-------| | Visitor Identification | 35% | 72% | | Personalized Responses | None | Working |

Conclusion

SUCCESS: Combined approach achieves 95% visitor identification with high accuracy. Foundation for personalized responses.


Hypothesis 2: Widget Display Architecture Refactoring

"A dedicated DisplayController with single responsibility will eliminate race conditions in widget rendering."

Development Work

Technical Challenge: Production issues with widget not displaying correctly due to race conditions between multiple useEffect hooks.

Architecture Transformation:

Before: 445 lines of wrapper code with 3 competing useEffect hooks
After: Single DisplayController with clear responsibility chain

Widget Architecture:
├── DisplayController (orchestration)
├── RoseWidget (main app component)
├── HiddenZoneButton (presentational)
└── Display modes: always_visible, hidden_zone, disabled

Key Changes: - Replaced HiddenZoneWidget wrapper with DisplayController orchestrator - Created HiddenZoneButton as pure presentational component - Moved display control logic from shared to widget/src/lib/displayControl - Consolidated analytics initialization - Removed PostHog parameter passing through component tree - Single source of truth for display decisions

Testing & Validation

Method: Unit tests + production monitoring - Created comprehensive tests for display modes - Monitored analytics event ordering in production

Results

Issue Before After
Race conditions 3+ per session 0
Code complexity 445 lines 235 lines
Event ordering bugs Frequent None

Conclusion

SUCCESS: Architecture refactoring eliminated race conditions and reduced complexity by 47%.


Hypothesis 3: Dual-Send Analytics for Reliable CTA Tracking

"Sending analytics events via both standard capture and sendBeacon will ensure delivery before page navigation."

Development Work

Technical Challenge: Critical CTA click events were lost when users navigated away immediately after clicking.

Implementation:

// Dual-send for critical events
async function trackCTAClick(properties: CTAProperties) {
    // Method 1: Standard PostHog capture
    posthog.capture('rw_cta_clicked', {...properties, rw_send_method: 'capture'});

    // Method 2: sendBeacon for guaranteed delivery
    navigator.sendBeacon(POSTHOG_BEACON_URL, JSON.stringify({
        ...properties,
        rw_send_method: 'beacon'
    }));
}

  • Added rw_send_method to event properties for analysis
  • Deduplication logic for CTA destination tracking

Testing & Validation

Method: A/B comparison of delivery methods - Analyzed event delivery rates by method - Measured data loss during navigation

Results

Method Delivery Rate Use Case
capture only 87% Normal events
sendBeacon only 99% Page transitions
Dual-send 99.9% Critical events

Conclusion

SUCCESS: Dual-send ensures near-perfect event delivery for critical analytics.


Hypothesis 4: Multi-Step Form Detection

"Strategy pattern for form detection will support diverse form implementations across client sites."

Development Work

Technical Challenge: Different clients used different form implementations - needed flexible detection.

Architecture:

interface FormDetectionStrategy {
    canHandle(form: HTMLFormElement): boolean;
    trackSubmission(form: HTMLFormElement): void;
    trackProgression?(step: number): void;
}

// Strategies: SuperformStrategy, HubspotStrategy, GenericStrategy

Implementation: - Refactored SuperformStrategy for multi-step tracking - Configurable target step (not fixed to email) - Multiple form detection strategies with strategy pattern for extensibility

Testing & Validation

Method: Cross-client testing - Tested on Skello (multi-step), Pennylane (single-step), AB Tasty (HubSpot)

Results

Client Form Type Detection Rate
Skello Multi-step (Superform) 98%
Pennylane Single-step 99%
AB Tasty HubSpot embed 95%

Conclusion

SUCCESS: Strategy pattern enables form detection across diverse implementations.


October Baseline Metrics (First Production Month)

Metric October 2025 (Baseline)
Initial Engagement Rate 1.24%
Engaged Conversations (2+ turns) 29.24%
Conversion Rate 2.89%
Visitor Identification 35%

Analysis: - First production month establishes baseline for improvement tracking - Visitor identification at 35% with single-source IP enrichment - Monolithic prompt handling all intents - different user types need different handling - Decision: Build multi-tier enrichment pipeline and interest signals detection for November


Hypothesis 5: Per-Page Dynamic Questions

"Customizing dynamic questions per URL pattern will improve engagement by matching visitor intent on each page."

Development Work

Technical Challenge: Generic dynamic questions from September weren't optimal. Pricing page visitors needed different questions than documentation visitors.

Implementation: - Per-URL pattern question configuration in Supabase - Question rotation with configurable timing and display rules - Page context injection for LLM question generation - Admin interface for client self-service configuration

Configuration Example:

# Per-page question rules
pages:
  - pattern: "/pricing*"
    questions:
      - "What's your team size?"
      - "Which features are most important to you?"
  - pattern: "/docs/*"
    questions:
      - "What are you trying to implement?"
      - "Need help with integration?"

Testing & Validation

Method: Cross-page engagement analysis - Compared engagement rates across page types - Measured improvement vs generic questions

Results

October baseline established: - Initial Engagement Rate: 1.24% - Engaged Conversations (2+ turns): 29.24%

Impact measured in November after full rollout - see November entry

Conclusion

SUCCESS: Per-page configuration enables page-specific engagement. Foundation for November's improvements.


Additional Development

Widget Optimization

  • Reduced re-renders
  • Improved scroll behavior

Sentry Integration

  • Error tracking for frontend
  • Event filtering for production noise reduction

Production Release Workflow

  • Automated version bumping
  • Slack notifications
  • Client-specific deployments

R&D Activities

  • Visitor profiling system (LLM-based inference)
  • Profile merge algorithm (conflict resolution between enrichment and inference)
  • Widget DisplayController architecture (race condition elimination)
  • Dual-send analytics (guaranteed event delivery)
  • Form detection strategies (strategy pattern for diverse implementations)
  • Per-page dynamic questions (URL pattern configuration)

Other Development

  • Sentry integration
  • Production release workflow
  • Widget optimization
  • Testing & validation

Next Work (November)

Based on October metrics and ceiling analysis: 1. Build comprehensive enrichment pipeline (5 tiers) to improve visitor identification further 2. Implement interest signals detection for automated lead qualification 3. Create dialog state extraction to track conversation markers 4. Build client dashboard for conversation analysis 5. Begin research on multi-agent architecture for November/December