Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@yosriady
Copy link
Contributor

@yosriady yosriady commented Nov 3, 2025

Note

Adds referral parsing configuration (query params and path regex) and passes Options into EventFactory via EventManager for traffic source extraction.

  • Referral Parsing (Traffic Sources):
    • Add configurable referral extraction via Options.referral with custom queryParams and pathPattern.
    • Compile pathPattern regex once; fall back to default params (ref, referral, refcode).
  • Event Pipeline Wiring:
    • EventManager now accepts Options and instantiates EventFactory(options).
    • FormoAnalytics passes options to EventManager.
  • Types:
    • Introduce ReferralOptions and add referral?: ReferralOptions to Options.

Written by Cursor Bugbot for commit 92b9e9c. This will update automatically on new commits. Configure here.

@linear
Copy link

linear bot commented Nov 3, 2025

@yosriady yosriady changed the title [P-1596] Referral parsing configuration (WIP) [P-1614] Referral parsing configuration (WIP) Nov 3, 2025
@linear
Copy link

linear bot commented Nov 3, 2025

@yosriady yosriady marked this pull request as ready for review November 3, 2025 06:41
@yosriady yosriady changed the title [P-1614] Referral parsing configuration (WIP) [P-1614] Referral parsing configuration Nov 3, 2025
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Introduces configurable traffic source parsing by extracting referral and UTM parameter logic into a dedicated TrafficSource service. Traffic data is parsed once during SDK initialization and stored in session storage, eliminating redundant URL parsing on every event.

Key Changes:

  • Created TrafficSource service with configurable referral detection via query parameters and path patterns
  • Moved traffic parsing from EventFactory to SDK initialization in FormoAnalytics
  • Simplified EventFactory.getTrafficSources() to retrieve stored data instead of parsing inline
  • Added ReferralOptions type for custom referral parameter and path pattern configuration
  • Reduced code duplication and improved separation of concerns

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • Well-architected refactoring that extracts traffic parsing into a dedicated service. The logic is moved from inline parsing to initialization-time parsing with session storage, which is a clean architectural improvement. No breaking changes to public APIs, and the fallback behavior is properly handled.
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
src/lib/traffic/TrafficSource.ts 5/5 New service for parsing and storing traffic sources (UTM params, referral codes) with configurable options
src/FormoAnalytics.ts 5/5 Initializes TrafficSource service on SDK init to parse and store traffic data from window.location.href
src/lib/event/EventFactory.ts 5/5 Simplified to retrieve stored traffic sources instead of parsing inline, reducing code duplication
src/types/base.ts 5/5 Added ReferralOptions interface and Options.referral field for configurable referral parsing

Sequence Diagram

sequenceDiagram
    participant SDK as FormoAnalytics
    participant TS as TrafficSource
    participant SS as SessionStorage
    participant EF as EventFactory
    
    Note over SDK,SS: SDK Initialization
    SDK->>TS: new TrafficSource(options.referral)
    SDK->>TS: parseAndStore(window.location.href)
    TS->>TS: extractUTMParameters(url)
    TS->>TS: extractReferralParameter(url)
    Note over TS: Check queryParams & pathPatterns
    TS->>SS: session().get(SESSION_TRAFFIC_SOURCE_KEY)
    SS-->>TS: stored traffic sources (or {})
    TS->>TS: Merge current + stored (prioritize current)
    TS->>SS: session().set(SESSION_TRAFFIC_SOURCE_KEY, merged)
    TS-->>SDK: ITrafficSource
    
    Note over SDK,EF: Event Creation
    SDK->>EF: create(event)
    EF->>EF: generateContext()
    EF->>SS: session().get(SESSION_TRAFFIC_SOURCE_KEY)
    SS-->>EF: stored traffic sources
    EF->>EF: Merge into event context
    EF-->>SDK: enriched event with traffic data
Loading

6 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@yosriady yosriady changed the title [P-1614] Referral parsing configuration feat: [P-1614] Referral parsing configuration Nov 3, 2025
@yosriady
Copy link
Contributor Author

yosriady commented Nov 3, 2025

bugbot run

cursor[bot]

This comment was marked as outdated.

@yosriady
Copy link
Contributor Author

yosriady commented Nov 4, 2025

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds configurable referral code extraction from URLs via custom query parameters and regex path patterns, enabling applications to track referral sources beyond the default ref, referral, and refcode query params.

Key Changes

  • Type Definitions: New ReferralOptions interface with queryParams and pathPatterns configuration
  • Event Pipeline Integration: FormoAnalyticsEventManagerEventFactory properly threads referral options through the initialization chain
  • Dual Extraction Logic: EventFactory.extractReferralParameter() checks custom/default query params first, then applies regex path patterns
  • Session Persistence: Referral codes merge with stored traffic sources and persist across page views

Implementation Notes

  • TrafficSource utility class was created with identical logic to EventFactory but is never imported or used, creating unnecessary code duplication
  • Both TrafficSource.extractReferralParameter() and EventFactory.extractReferralParameter() implement the same pattern-matching algorithm
  • The TrafficSource class also includes a full parseAndStore() method that mirrors EventFactory.getTrafficSources()

Confidence Score: 4/5

  • Safe to merge with minor code duplication that should be addressed in a follow-up
  • Core functionality is implemented correctly and wired through the entire event pipeline with proper error handling. The main issue is the unused TrafficSource utility class that duplicates logic already in EventFactory, which creates technical debt but doesn't affect runtime behavior.
  • Review src/lib/traffic/TrafficSource.ts - consider either using this class in EventFactory or removing it to eliminate code duplication

Important Files Changed

File Analysis

Filename Score Overview
src/types/base.ts 5/5 Added well-documented ReferralOptions interface with clear examples
src/lib/event/EventFactory.ts 4/5 Implements referral extraction with custom params and path patterns, but duplicates logic from unused TrafficSource class
src/lib/traffic/TrafficSource.ts 3/5 New utility class created but never imported or used anywhere - duplicates functionality already in EventFactory

Sequence Diagram

sequenceDiagram
    participant User as User/Developer
    participant FA as FormoAnalytics
    participant EM as EventManager
    participant EF as EventFactory
    participant Session as SessionStorage
    
    User->>FA: init(writeKey, options)
    FA->>FA: options.referral = {queryParams, pathPatterns}
    FA->>EM: new EventManager(eventQueue, options.referral)
    EM->>EF: new EventFactory(referralOptions)
    EF->>EF: Store referralOptions
    
    Note over User,Session: On page load or navigation
    
    EF->>EF: generateContext()
    EF->>EF: getTrafficSources(window.location.href)
    EF->>EF: extractUTMParameters(url)
    EF->>EF: extractReferralParameter(urlObj)
    
    alt Custom query params configured
        EF->>EF: Check custom queryParams
        EF-->>EF: Return ref if found
    else Default query params
        EF->>EF: Check ["ref", "referral", "refcode"]
        EF-->>EF: Return ref if found
    end
    
    alt Path patterns configured
        EF->>EF: Match pathname against pathPatterns
        EF->>EF: Extract capture group [1]
        EF-->>EF: Return referral code from path
    end
    
    EF->>Session: Get stored traffic sources
    Session-->>EF: Return stored ITrafficSource
    EF->>EF: Merge current + stored sources
    EF->>Session: Save merged traffic sources
    EF-->>FA: Return enriched event with traffic data
Loading

6 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 97 to 129
private extractReferralParameter = (urlObj: URL): string => {
const referralParams = ["ref", "referral", "refcode"];
// Get query parameter names to check (default or custom)
const defaultParams = ["ref", "referral", "refcode"];
const referralParams =
this.referralOptions?.queryParams || defaultParams;

// Check query parameters first
for (const param of referralParams) {
const value = urlObj.searchParams.get(param)?.trim();
if (value) return value;
}

// Check URL path patterns if configured
if (this.referralOptions?.pathPatterns?.length) {
const pathname = urlObj.pathname;
for (const pattern of this.referralOptions.pathPatterns) {
try {
const regex = new RegExp(pattern);
const match = pathname.match(regex);
if (match && match[1]) {
const referralCode = match[1].trim();
if (referralCode) return referralCode;
}
} catch (error) {
logger.warn(
`Invalid referral path pattern: ${pattern}. Error: ${error}`
);
}
}
}

return "";
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Duplicates logic from TrafficSource.extractReferralParameter - consider using TrafficSource class instead of duplicating code

@yosriady
Copy link
Contributor Author

yosriady commented Nov 5, 2025

@greptile

@yosriady
Copy link
Contributor Author

yosriady commented Nov 5, 2025

bugbot run

const referralParams =
this.options?.referral?.queryParams || defaultParams;

// Check query parameters first
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Referral extraction conflict with partial config using path patterns

When users configure ONLY pathPatterns without queryParams (Example 2 in docs), the code still checks default query parameters ["ref", "referral", "refcode"] because this.options?.referral?.queryParams || defaultParams falls back to defaultParams when queryParams is undefined. This breaks the user's intention to only use path-based referral extraction. For example, with config { pathPatterns: ['/r/([^/]+)'] }, the URL http://localhost:3000/r/ABC123?ref=XYZ789 would capture "XYZ789" instead of "ABC123". The fix should only use default params when no referral configuration exists at all, not when partial configuration (only pathPatterns) is provided.

Fix in Cursor Fix in Web

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds flexible referral code extraction to the analytics SDK, allowing custom query parameters and URL path patterns.

Key Changes:

  • Options flow: FormoAnalytics.init()EventManagerEventFactory
  • EventFactory.extractReferralParameter() checks custom query params first, then path patterns
  • Priority order: custom/default query params → path patterns → empty string
  • Invalid regex patterns are caught and logged with warning
  • Comprehensive documentation with 6+ example configurations

Implementation:

  • Query params default to ["ref", "referral", "refcode"] if not configured
  • Path patterns use first capture group ([^/]+) from regex match
  • Extracted codes are trimmed for whitespace
  • First-touch attribution preserved via session storage

Confidence Score: 5/5

  • Safe to merge - well-structured feature with proper error handling and comprehensive documentation
  • Clean implementation with proper error handling for regex patterns, good fallback defaults, clear options propagation through the system, extensive documentation, and follows existing patterns in the codebase
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
src/lib/event/EventManager.ts 5/5 Updated to accept and forward options to EventFactory for referral parsing configuration
src/lib/event/EventFactory.ts 4/5 Implements custom referral extraction from query params and URL path patterns with error handling; query params checked before path patterns
src/types/base.ts 5/5 Added ReferralOptions interface with inline examples and documentation for query params and path patterns

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventManager
    participant EventFactory
    participant URL as URL/Location
    
    User->>FormoAnalytics: init(writeKey, options)
    Note over FormoAnalytics: options.referral = { queryParams, pathPatterns }
    FormoAnalytics->>EventManager: new EventManager(eventQueue, options)
    EventManager->>EventFactory: new EventFactory(options)
    Note over EventFactory: Stores options.referral config
    
    User->>URL: Navigate to page with referral
    Note over URL: e.g., ?via=CODE or /r/CODE
    
    FormoAnalytics->>EventManager: addEvent(pageEvent)
    EventManager->>EventFactory: create(event)
    EventFactory->>EventFactory: generateContext()
    EventFactory->>EventFactory: getTrafficSources(url)
    EventFactory->>EventFactory: extractReferralParameter(urlObj)
    
    alt Check Query Parameters
        EventFactory->>URL: urlObj.searchParams.get(param)
        URL-->>EventFactory: referral code or null
        Note over EventFactory: Uses custom queryParams or defaults
    end
    
    alt No Query Param Found
        EventFactory->>URL: urlObj.pathname
        URL-->>EventFactory: pathname string
        loop For each pathPattern
            EventFactory->>EventFactory: new RegExp(pattern).match(pathname)
            Note over EventFactory: Extract from first capture group
        end
    end
    
    EventFactory-->>EventManager: event with ref field populated
    EventManager->>EventManager: enqueue event
    EventManager-->>FormoAnalytics: event queued
Loading

7 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

cursor[bot]

This comment was marked as outdated.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds configurable referral code extraction to support custom query parameters and URL path regex patterns.

Key Changes:

  • New ReferralOptions interface with queryParams and pathPatterns configuration
  • Enhanced extractReferralParameter method to check custom query params (defaults: ['ref', 'referral', 'refcode']) then match path patterns using regex
  • Options passed through FormoAnalyticsEventManagerEventFactory initialization chain
  • Comprehensive documentation with examples for influencer tracking, affiliate programs, and various URL formats
  • Error handling for invalid regex patterns with warning logs

Priority: Query parameters checked before path patterns (first match wins)

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk - straightforward feature addition with good error handling
  • Score reflects well-structured implementation with proper type safety, error handling for invalid regex patterns, and comprehensive documentation. Minor confidence reduction due to the previous comment about potential code duplication (though TrafficSource.extractReferralParameter doesn't appear to exist in the current codebase).
  • No files require special attention

Important Files Changed

File Analysis

Filename Score Overview
src/types/base.ts 5/5 Added ReferralOptions interface and referral field to Options with comprehensive documentation
src/lib/event/EventFactory.ts 4/5 Added constructor to accept options, enhanced extractReferralParameter to support custom query params and path patterns with error handling
REFERRAL_CONFIG_EXAMPLES.md 5/5 Comprehensive documentation with examples, use cases, and testing instructions for referral configuration

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventManager
    participant EventFactory
    participant EventQueue
    
    User->>FormoAnalytics: init(writeKey, options)
    Note over FormoAnalytics: options.referral config
    FormoAnalytics->>EventManager: new EventManager(eventQueue, options)
    EventManager->>EventFactory: new EventFactory(options)
    Note over EventFactory: Store options.referral config
    
    User->>FormoAnalytics: page/track/connect event
    FormoAnalytics->>EventManager: addEvent(event)
    EventManager->>EventFactory: create(event)
    EventFactory->>EventFactory: generateContext()
    EventFactory->>EventFactory: getTrafficSources(url)
    EventFactory->>EventFactory: extractReferralParameter(urlObj)
    
    alt Query params configured
        EventFactory->>EventFactory: Check custom queryParams
        Note over EventFactory: options.referral.queryParams || defaults
    end
    
    alt Path patterns configured
        EventFactory->>EventFactory: Check pathPatterns
        Note over EventFactory: Match regex patterns on pathname
    end
    
    EventFactory-->>EventManager: return enriched event with ref
    EventManager->>EventQueue: enqueue(formoEvent)
    EventQueue-->>User: Event sent to Formo
Loading

5 files reviewed, no comments

Edit Code Review Agent Settings | Greptile

@yosriady
Copy link
Contributor Author

yosriady commented Nov 6, 2025

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds configurable referral code parsing to the SDK, enabling custom query parameters and URL path patterns for extracting referral codes. The implementation wires Options through FormoAnalyticsEventManagerEventFactory.

Key Changes:

  • EventFactory now accepts Options in constructor and stores referral configuration
  • extractReferralParameter prioritizes custom query params over path patterns, with regex-based path matching
  • Error handling added for invalid regex patterns with logger warnings
  • Documentation provided with extensive configuration examples

Issue Found:

  • Logic bug in EventFactory.ts:103-105 - when users configure only pathPatterns without specifying queryParams, the code uses an empty array instead of defaulting to ["ref", "referral", "refcode"], breaking the documented default behavior

Confidence Score: 3/5

  • PR has a logic bug that will cause unexpected behavior when only path patterns are configured
  • The logic error where default query params aren't used when queryParams is undefined (but referral config exists) contradicts the type definition's @default annotation and will break expected behavior. The fix is simple (use ?? instead of ||), but this needs to be corrected before merge.
  • Pay close attention to src/lib/event/EventFactory.ts line 103-105 - fix the nullish coalescing logic

Important Files Changed

File Analysis

Filename Score Overview
src/lib/event/EventFactory.ts 3/5 Added configurable referral parsing with constructor injection of options. Logic bug: default query params not used when only pathPatterns configured.

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventManager
    participant EventFactory
    participant Browser
    
    User->>FormoAnalytics: init(writeKey, options)
    FormoAnalytics->>EventManager: new EventManager(eventQueue, options)
    EventManager->>EventFactory: new EventFactory(options)
    Note over EventFactory: Stores options.referral config
    
    User->>Browser: Navigate to URL with referral
    Browser->>FormoAnalytics: page() / track() event
    FormoAnalytics->>EventManager: track(event)
    EventManager->>EventFactory: create(event)
    EventFactory->>EventFactory: generateContext()
    EventFactory->>EventFactory: getTrafficSources(url)
    EventFactory->>EventFactory: extractReferralParameter(urlObj)
    
    alt Query params configured/default
        EventFactory->>Browser: urlObj.searchParams.get(param)
        Browser-->>EventFactory: referral code or null
    end
    
    alt No query param found & path patterns configured
        EventFactory->>Browser: urlObj.pathname.match(pattern)
        Browser-->>EventFactory: regex match with capture group
    end
    
    EventFactory-->>EventManager: enriched event with ref field
    EventManager-->>FormoAnalytics: event queued
    FormoAnalytics-->>User: event tracked
Loading

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 103 to 105
const referralParams = !this.options?.referral
? defaultParams // No referral config at all → use defaults
: (this.options.referral.queryParams || []); // Has config → use queryParams or empty array
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: When options.referral exists but queryParams is undefined (e.g., user only sets pathPatterns), this uses [] instead of defaultParams. This means default query params (ref, referral, refcode) won't work when only configuring path patterns, which contradicts the @default JSDoc comment in the type definition.

Suggested change
const referralParams = !this.options?.referral
? defaultParams // No referral config at all → use defaults
: (this.options.referral.queryParams || []); // Has config → use queryParams or empty array
const referralParams = !this.options?.referral
? defaultParams // No referral config at all → use defaults
: (this.options.referral.queryParams ?? defaultParams); // Has config → use queryParams or defaults

@yosriady
Copy link
Contributor Author

yosriady commented Nov 6, 2025

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds configurable referral code parsing to the analytics SDK. Users can now customize query parameters and URL path patterns for extracting referral codes.

Key Changes:

  • EventFactory constructor now accepts Options parameter with referral configuration
  • extractReferralParameter enhanced to support custom query params and regex path patterns
  • Default fallback behavior maintained (ref, referral, refcode query params)
  • Path pattern matching uses regex with capture group extraction
  • Proper error handling for invalid regex patterns with warning logs
  • Wired through EventManagerEventFactoryFormoAnalytics.init()

Implementation Notes:

  • Query params are checked first, then path patterns
  • Path patterns use first capture group [1] for referral code
  • Invalid regex patterns log warning and continue without crashing
  • Previous logic bug regarding default params has been properly addressed

Confidence Score: 4/5

  • This PR is safe to merge with minor performance considerations.
  • The implementation is clean, well-structured, and properly handles edge cases. The previous logic bug mentioned in comments has been fixed. Only minor performance optimization suggested (regex compilation in loop), but this is not critical for typical usage patterns. No security issues or breaking changes detected.
  • No files require special attention. The EventFactory.ts changes are straightforward and well-implemented.

Important Files Changed

File Analysis

Filename Score Overview
src/lib/event/EventFactory.ts 4/5 Adds constructor to accept Options, implements configurable referral parsing with query params and path patterns. Previous logic bug about default params has been fixed.

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventManager
    participant EventFactory
    participant EventQueue

    User->>FormoAnalytics: init(writeKey, options)
    FormoAnalytics->>EventManager: new EventManager(eventQueue, options)
    EventManager->>EventFactory: new EventFactory(options)
    EventFactory->>EventFactory: Store options.referral config
    
    Note over EventFactory: Referral Config Stored:<br/>- queryParams: ["ref", "referral", "refcode"]<br/>- pathPatterns: ["/r/([^/]+)", ...]

    User->>FormoAnalytics: page() / track() / etc
    FormoAnalytics->>EventManager: addEvent(event)
    EventManager->>EventFactory: create(event)
    
    EventFactory->>EventFactory: generateContext()
    EventFactory->>EventFactory: getTrafficSources(url)
    EventFactory->>EventFactory: extractReferralParameter(urlObj)
    
    alt Query Params Configured
        EventFactory->>EventFactory: Check configured queryParams
        EventFactory-->>EventFactory: Return first match or ""
    end
    
    alt Path Patterns Configured
        EventFactory->>EventFactory: Match pathname against patterns
        EventFactory->>EventFactory: Extract capture group [1]
        EventFactory-->>EventFactory: Return matched code or ""
    end
    
    EventFactory-->>EventManager: Return IFormoEvent with context.ref
    EventManager->>EventQueue: enqueue(formoEvent)
    EventQueue-->>User: Event tracked
Loading

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

const pathname = urlObj.pathname;
for (const pattern of this.options.referral.pathPatterns) {
try {
const regex = new RegExp(pattern);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Creating RegExp in a loop can impact performance if patterns are complex or arrays are large. Consider validating and compiling patterns once in the constructor.

@yosriady
Copy link
Contributor Author

yosriady commented Nov 6, 2025

@greptile

@yosriady
Copy link
Contributor Author

yosriady commented Nov 6, 2025

bugbot run

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

This PR adds configurable referral parameter parsing to the SDK, enabling extraction of referral codes from both custom query parameters and URL path patterns via regex.

Key changes:

  • Adds ReferralOptions interface with queryParams and pathPattern fields
  • EventFactory now accepts options and parses referrals from configured query params (defaults: ref, referral, refcode) or URL path patterns
  • Options are threaded through FormoAnalyticsEventManagerEventFactory
  • Includes error handling for invalid regex patterns with logging

Issues found:

  • Regex compilation happens on every event instead of once at initialization (performance concern)

Confidence Score: 4/5

  • Safe to merge with minor performance optimization recommended
  • Implementation is solid with proper error handling and fallback logic. The regex compilation pattern could be optimized but doesn't affect correctness. Previous logical issue with default params has been fixed.
  • src/lib/event/EventFactory.ts - consider caching compiled regex pattern for better performance

Important Files Changed

File Analysis

Filename Score Overview
src/lib/event/EventFactory.ts 4/5 Adds referral parsing configuration with query params and path pattern support, includes error handling for invalid regex patterns
src/types/base.ts 5/5 Adds ReferralOptions interface with clear JSDoc examples and adds referral field to Options interface
src/lib/event/EventManager.ts 5/5 Updates constructor to accept and pass Options to EventFactory for referral config support
src/FormoAnalytics.ts 5/5 Passes options to EventManager constructor to enable referral configuration

Sequence Diagram

sequenceDiagram
    participant User
    participant FormoAnalytics
    participant EventManager
    participant EventFactory
    participant URL as URL/Query Params
    
    User->>FormoAnalytics: new FormoAnalytics(writeKey, options)
    Note over FormoAnalytics: options.referral = {<br/>queryParams: ["via"],<br/>pathPattern: "/r/([^/]+)"<br/>}
    FormoAnalytics->>EventManager: new EventManager(eventQueue, options)
    EventManager->>EventFactory: new EventFactory(options)
    Note over EventFactory: Store options.referral config
    
    User->>FormoAnalytics: track/page/identify event
    FormoAnalytics->>EventManager: create event
    EventManager->>EventFactory: generateEvent()
    EventFactory->>EventFactory: generateContext()
    EventFactory->>EventFactory: getTrafficSources()
    EventFactory->>EventFactory: extractReferralParameter(urlObj)
    
    alt Check query params first
        EventFactory->>URL: Check custom params (via, etc)
        URL-->>EventFactory: Return ref value if found
    else No query param match
        EventFactory->>URL: Apply pathPattern regex to pathname
        URL-->>EventFactory: Return capture group [1] if matched
    end
    
    EventFactory-->>EventManager: Event with ref in context
    EventManager-->>FormoAnalytics: Enriched event
    FormoAnalytics->>User: Event queued
Loading

3 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

if (this.options?.referral?.pathPattern) {
const pathname = urlObj.pathname;
try {
const regex = new RegExp(this.options.referral.pathPattern);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Regex compilation happens on every event. For better performance, compile once in constructor and cache.

Suggested change
const regex = new RegExp(this.options.referral.pathPattern);
private compiledPathPattern?: RegExp;
constructor(options?: Options) {
this.options = options;
if (options?.referral?.pathPattern) {
try {
this.compiledPathPattern = new RegExp(options.referral.pathPattern);
} catch (error) {
logger.warn(`Invalid referral path pattern: ${options.referral.pathPattern}`);
}
}
}
// Then in extractReferralParameter:
if (this.compiledPathPattern) {
const match = urlObj.pathname.match(this.compiledPathPattern);
// ...
}

@yosriady
Copy link
Contributor Author

yosriady commented Nov 6, 2025

@greptile

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Greptile Overview

Greptile Summary

Adds configurable referral code parsing from URLs via custom query parameters or regex path patterns. The Options.referral config is threaded through FormoAnalyticsEventManagerEventFactory, where referral codes are extracted during traffic source collection.

Key changes:

  • EventFactory constructor accepts Options and compiles pathPattern regex once for performance
  • extractReferralParameter checks query params first (using custom or default ["ref", "referral", "refcode"]), then falls back to path pattern matching if configured
  • Wiring complete: options flow from SDK initialization to event creation

Previous feedback addressed:

  • Logic fix applied for queryParams fallback to defaults when only pathPattern is configured
  • Regex compilation moved to constructor (previously was in loop)
  • Comment about TrafficSource class duplication is not applicable (class doesn't exist)

Confidence Score: 4/5

  • Safe to merge with minor style improvements from existing comments
  • Implementation is logically sound after previous fixes were applied. Referral parsing logic correctly handles all config scenarios (no config, partial config, full config). Regex compiled once in constructor for performance. Previous logic bug with queryParams fallback has been addressed. Only remaining items are non-critical style suggestions already documented in comments.
  • No files require special attention - all critical issues have been resolved

Important Files Changed

File Analysis

Filename Score Overview
src/lib/event/EventFactory.ts 4/5 Adds configurable referral parsing with query params and path patterns. Logic is sound after previous fixes, with regex compiled once in constructor for performance. Minor style issues noted in existing comments.

Sequence Diagram

sequenceDiagram
    participant App as FormoAnalytics
    participant EM as EventManager
    participant EF as EventFactory
    participant URL as URL/Document

    App->>EM: new EventManager(eventQueue, options)
    EM->>EF: new EventFactory(options)
    Note over EF: Compile referral.pathPattern<br/>regex in constructor
    
    App->>EM: addEvent(event, address, userId)
    EM->>EF: create(event, address, userId)
    EF->>EF: generateContext()
    EF->>EF: getTrafficSources(location.href)
    EF->>URL: Parse URL
    EF->>EF: extractReferralParameter(urlObj)
    
    alt Query params check
        EF->>URL: Check custom/default query params<br/>(ref, referral, refcode)
        alt Found in query param
            URL-->>EF: Return referral code
        end
    end
    
    alt Path pattern check (if configured)
        EF->>URL: Match pathname with compiledPathPattern
        alt Regex match found
            URL-->>EF: Return capture group [1]
        end
    end
    
    EF-->>EM: Return enriched event with ref
    EM->>EM: Check blocked addresses
    EM->>EM: eventQueue.enqueue(formoEvent)
Loading

1 file reviewed, no comments

Edit Code Review Agent Settings | Greptile

@yosriady yosriady merged commit e586a05 into main Nov 6, 2025
8 checks passed
@yosriady yosriady deleted the p-1596 branch November 6, 2025 07:55
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.

2 participants