@@ -8,45 +8,75 @@ const initOutboundDomains = () => {
88 } = window . _dubAnalytics ;
99 let outboundLinksUpdated = new Set ( ) ; // Track processed links
1010
11+ function normalizeDomain ( domain ) {
12+ return domain . replace ( / ^ w w w \. / , '' ) . trim ( ) ;
13+ }
14+
15+ function isMatchingDomain ( url , domain ) {
16+ try {
17+ const urlHostname = new URL ( url ) . hostname ;
18+ const normalizedUrlHostname = normalizeDomain ( urlHostname ) ;
19+ const normalizedDomain = normalizeDomain ( domain ) ;
20+
21+ // Exact match after removing www.
22+ return normalizedUrlHostname === normalizedDomain ;
23+ } catch ( e ) {
24+ return false ;
25+ }
26+ }
27+
1128 function addOutboundTracking ( clickId ) {
12- // Parse comma-separated outbound domains
13- const outboundDomains = DOMAINS_CONFIG . outbound
14- ?. split ( ',' )
15- . map ( ( d ) => d . trim ( ) ) ;
29+ // Handle both string and array configurations for outbound domains
30+ const outboundDomains = Array . isArray ( DOMAINS_CONFIG . outbound )
31+ ? DOMAINS_CONFIG . outbound
32+ : DOMAINS_CONFIG . outbound ?. split ( ',' ) . map ( ( d ) => d . trim ( ) ) ;
33+
1634 if ( ! outboundDomains ?. length ) return ;
1735
18- const currentDomain = HOSTNAME . replace ( / ^ w w w \. / , '' ) ;
19- const filteredDomains = outboundDomains . filter ( ( d ) => d !== currentDomain ) ;
36+ const currentDomain = normalizeDomain ( HOSTNAME ) ;
37+ const filteredDomains = outboundDomains
38+ . map ( normalizeDomain )
39+ . filter ( ( d ) => d !== currentDomain ) ;
2040
2141 const existingCookie = clickId || cookieManager . get ( DUB_ID_VAR ) ;
2242 if ( ! existingCookie ) return ;
2343
24- // Create selectors for both links and iframes
25- const selectors = filteredDomains
26- . map ( ( domain ) => [ `a[href*="${ domain } "]` , `iframe[src*="${ domain } "]` ] )
27- . flat ( )
28- . join ( ',' ) ;
29-
30- const elements = document . querySelectorAll ( selectors ) ;
44+ // Get all links and iframes
45+ const elements = document . querySelectorAll ( 'a[href], iframe[src]' ) ;
3146 if ( ! elements || elements . length === 0 ) return ;
3247
3348 elements . forEach ( ( element ) => {
3449 // Skip already processed elements
3550 if ( outboundLinksUpdated . has ( element ) ) return ;
3651
3752 try {
38- const url = new URL ( element . href || element . src ) ;
39- url . searchParams . set ( DUB_ID_VAR , existingCookie ) ;
40-
41- // Update the appropriate attribute based on element type
42- if ( element . tagName . toLowerCase ( ) === 'a' ) {
43- element . href = url . toString ( ) ;
44- } else if ( element . tagName . toLowerCase ( ) === 'iframe' ) {
45- element . src = url . toString ( ) ;
46- }
53+ const urlString = element . href || element . src ;
54+ if ( ! urlString ) return ;
55+
56+ // Check if the URL matches any of our outbound domains
57+ const isOutbound = filteredDomains . some ( ( domain ) =>
58+ isMatchingDomain ( urlString , domain ) ,
59+ ) ;
60+ if ( ! isOutbound ) return ;
61+
62+ const url = new URL ( urlString ) ;
4763
48- outboundLinksUpdated . add ( element ) ;
49- } catch ( e ) { }
64+ // Only add the tracking parameter if it's not already present
65+ if ( ! url . searchParams . has ( DUB_ID_VAR ) ) {
66+ url . searchParams . set ( DUB_ID_VAR , existingCookie ) ;
67+
68+ // Update the appropriate attribute based on element type
69+ if ( element . tagName . toLowerCase ( ) === 'a' ) {
70+ element . href = url . toString ( ) ;
71+ } else if ( element . tagName . toLowerCase ( ) === 'iframe' ) {
72+ element . src = url . toString ( ) ;
73+ }
74+
75+ outboundLinksUpdated . add ( element ) ;
76+ }
77+ } catch ( e ) {
78+ console . error ( 'Error processing element:' , e ) ;
79+ }
5080 } ) ;
5181 }
5282
0 commit comments