Skip to content

Comments

feat: add PII filtering for UTM parameters#11

Merged
jackmisner merged 1 commit intomainfrom
feature/pii-filtering
Feb 13, 2026
Merged

feat: add PII filtering for UTM parameters#11
jackmisner merged 1 commit intomainfrom
feature/pii-filtering

Conversation

@jackmisner
Copy link
Owner

@jackmisner jackmisner commented Feb 13, 2026

Summary

🤖 Generated with Nori

  • Add PII (Personally Identifiable Information) filtering to the UTM capture pipeline, detecting and handling email addresses and phone numbers in parameter values
  • Support two modes: reject (discard values containing PII) and redact (replace with [REDACTED]), plus an optional strict allowlist pattern
  • Disabled by default (piiFiltering: { enabled: false }) — zero impact on existing users

What changed

  • New module src/core/pii-filter.ts with detectPii, filterValue, filterParams
  • Types PiiPattern and PiiFilterConfig in src/types/index.ts
  • Config defaults DEFAULT_PII_PATTERNS (email, phone_international, phone_uk, phone_us) and DEFAULT_PII_FILTER_CONFIG
  • Config loader updated with mergePiiFilterConfig, plus validation for pattern objects, allowlistPattern, and onPiiDetected
  • Capture pipeline integration — PII filtering runs after sanitization
  • React hook forwards piiFiltering config to captureUtmParameters
  • Barrel exports updated across src/core/index.ts, src/config/index.ts, src/index.ts
  • README updated with PII filtering API docs, examples, and config table entry
  • Noridocs updated across all docs.md files

Test Plan

  • 35 new unit tests for detectPii, filterValue, filterParams (reject/redact modes, allowlist, callback, callback resilience, false positive checks, disabled patterns, edge cases)
  • 6 new config validation tests (pattern object validation, allowlistPattern, onPiiDetected)
  • 5 capture integration tests (reject, passthrough, disabled, camelCase, combined with sanitization)
  • 1 React hook PII forwarding test
  • All 324 tests pass, format/lint/type checks clean

Share Nori with your team: https://www.npmjs.com/package/nori-ai

Summary by CodeRabbit

Release Notes

  • New Features

    • Added PII filtering capability to detect and handle personally identifiable information in UTM parameters, including email addresses and phone numbers.
    • Configurable filtering modes: reject (removes PII values) or redact (replaces with [REDACTED]).
    • Optional allowlist pattern and callback support for custom PII handling.
    • Feature disabled by default for backward compatibility.
  • Documentation

    • Updated README with PII filtering feature description, configuration options, and usage examples.
  • Tests

    • Added comprehensive test coverage for PII filtering functionality and configuration handling.

Detect and filter personally identifiable information (emails, phone
numbers) from UTM parameter values at capture time. Supports reject
mode (discard values) and redact mode (replace with [REDACTED]),
optional strict allowlist patterns, and an onPiiDetected callback.
Disabled by default.
🤖 Generated with [Nori](https://nori.ai)

Co-Authored-By: Nori <contact@tilework.tech>
@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

Walkthrough

Adds a comprehensive PII filtering feature to the UTM parameter tracking library. Introduces detection patterns (email, phone formats), multiple filtering modes (reject/redact), allowlist support, and optional callbacks. Integrates into the capture pipeline to filter PII values after sanitisation, including configuration defaults, type definitions, and extensive test coverage.

Changes

Cohort / File(s) Summary
Documentation and Configuration
README.md, src/docs.md, src/config/docs.md, src/types/docs.md, __tests__/docs.md
Adds PII filtering feature documentation, configuration examples, usage patterns, type references, and test coverage descriptions across README, core, config, types, and test documentation.
Type Definitions
src/types/index.ts
Introduces new interfaces: PiiPattern (named regex with enabled toggle) and PiiFilterConfig (mode, patterns array, optional allowlist and callback). Extends UtmConfig and ResolvedUtmConfig with partial/required piiFiltering fields respectively.
Configuration Defaults and Loading
src/config/defaults.ts, src/config/loader.ts, src/config/index.ts
Exports DEFAULT_PII_PATTERNS and DEFAULT_PII_FILTER_CONFIG constants. Adds mergePiiFilterConfig() helper and integrates PII filtering into createConfig() and mergeConfig(). Extends validation in validateConfig() to cover PII filtering configuration fields.
Core PII Filtering Implementation
src/core/pii-filter.ts, src/core/index.ts, src/core/docs.md
Implements detectPii(), filterValue(), and filterParams() functions for PII detection and filtering. Supports reject/redact modes, allowlist matching, error-safe callbacks, and pattern precedence logic. Documents integration into capture pipeline after sanitisation.
Capture Integration
src/core/capture.ts
Extends CaptureOptions with optional piiFiltering field. Updates captureUtmParameters() to apply PII filtering after sanitisation, merging user-provided and default configurations.
Public API Surface
src/index.ts
Exports three new PII filtering functions (detectPii, filterValue, filterParams), two configuration constants (DEFAULT_PII_PATTERNS, DEFAULT_PII_FILTER_CONFIG), and two types (PiiPattern, PiiFilterConfig).
React Integration
src/react/useUtmTracking.ts, src/react/docs.md
Propagates config.piiFiltering to captureUtmParameters() options within the hook, enabling PII filtering in React component context.
Configuration Tests
__tests__/config/loader.test.ts
Adds comprehensive unit tests validating default values, merging behaviour, and validation rules for all piiFiltering configuration fields (enabled, mode, patterns, allowlistPattern, onPiiDetected).
Core Feature Tests
__tests__/core/pii-filter.test.ts
Comprehensive test suite covering detectPii() (email, phone formats, disabled patterns), filterValue() (reject/redact/allowlist modes, callbacks), filterParams() (parameter filtering, key normalisation), and edge cases (callback error handling, precedence rules).
Capture Integration Tests
__tests__/core/capture.test.ts, __tests__/react/useUtmTracking.test.tsx
Adds tests for PII filtering integration with captureUtmParameters() across enabled/disabled states and with camelCase formatting. Adds React hook tests verifying PII values are removed when filtering is enabled.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Capture as captureUtmParameters()
    participant Parse as Parse & Extract
    participant Allow as Allowlist Filter
    participant Sanitize as Sanitisation
    participant PII as PII Filter
    participant Format as Format Keys
    participant Result as Result

    App->>Capture: url + options (piiFiltering)
    Capture->>Parse: Extract UTM parameters
    Parse->>Allow: Filter by allowedParameters
    Allow->>Sanitize: Apply sanitisation
    Sanitize->>PII: Apply PII filtering<br/>(enabled check)
    PII->>PII: Detect PII via patterns<br/>Check allowlist
    PII->>PII: Invoke callback if PII found<br/>(reject/redact mode)
    PII->>Format: Filtered parameters
    Format->>Result: Apply key formatting<br/>(camelCase, etc.)
    Result->>App: Return utmParameters
Loading
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add PII filtering for UTM parameters' is clear, concise, and directly describes the primary feature addition in the changeset.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
src/config/defaults.ts (1)

50-54: Consider deep‑cloning pattern objects (and RegExp) to avoid shared state.
Array spreads keep the same pattern objects/RegExp instances across exported defaults; cloning prevents accidental mutation and any future /g lastIndex bleed.

♻️ Suggested change
 export const DEFAULT_PII_FILTER_CONFIG: PiiFilterConfig = {
   enabled: false,
   mode: 'reject',
-  patterns: [...DEFAULT_PII_PATTERNS],
+  patterns: DEFAULT_PII_PATTERNS.map((p) => ({
+    ...p,
+    pattern: new RegExp(p.pattern.source, p.pattern.flags),
+  })),
 }
@@
-  piiFiltering: { ...DEFAULT_PII_FILTER_CONFIG, patterns: [...DEFAULT_PII_PATTERNS] },
+  piiFiltering: {
+    ...DEFAULT_PII_FILTER_CONFIG,
+    patterns: DEFAULT_PII_PATTERNS.map((p) => ({
+      ...p,
+      pattern: new RegExp(p.pattern.source, p.pattern.flags),
+    })),
+  },
@@
     piiFiltering: {
       ...DEFAULT_CONFIG.piiFiltering,
-      patterns: DEFAULT_CONFIG.piiFiltering.patterns.map((p) => ({ ...p })),
+      patterns: DEFAULT_CONFIG.piiFiltering.patterns.map((p) => ({
+        ...p,
+        pattern: new RegExp(p.pattern.source, p.pattern.flags),
+      })),
     },

Also applies to: 103-105, 119-122

src/core/pii-filter.ts (1)

90-111: Implementation correctly handles both modes and undefined values.

The logic for omitting keys in reject mode (lines 104-106) versus preserving them with [REDACTED] in redact mode is correct.

Minor observation: The type cast on line 110 (as UtmParameters) is safe given the function signature guarantees the input type, but a more type-safe approach could use generics:

♻️ Optional: Generic type-safe alternative
-export function filterParams(params: UtmParameters, config: PiiFilterConfig): UtmParameters {
+export function filterParams<T extends UtmParameters>(params: T, config: PiiFilterConfig): T {
   if (!config.enabled) {
-    return { ...params }
+    return { ...params } as T
   }
 
-  const result: Record<string, string | undefined> = {}
+  const result: Partial<T> = {}
   // ... rest of implementation
-  return result as UtmParameters
+  return result as T
 }

Comment @coderabbitai help to get the list of available commands and usage tips.

@jackmisner jackmisner merged commit e62fe7a into main Feb 13, 2026
5 checks passed
@jackmisner jackmisner deleted the feature/pii-filtering branch February 13, 2026 19:54
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