@@ -8,36 +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- const selector = filteredDomains
25- . map ( ( domain ) => ` a[href*=" ${ domain } "]` )
26- . join ( ',' ) ;
44+ // Get all links and iframes
45+ const elements = document . querySelectorAll ( ' a[href], iframe[src]' ) ;
46+ if ( ! elements || elements . length === 0 ) return ;
2747
28- const links = document . querySelectorAll ( selector ) ;
29- if ( ! links || links . length === 0 ) return ;
30-
31- links . forEach ( ( link ) => {
32- // Skip already processed links
33- if ( outboundLinksUpdated . has ( link ) ) return ;
48+ elements . forEach ( ( element ) => {
49+ // Skip already processed elements
50+ if ( outboundLinksUpdated . has ( element ) ) return ;
3451
3552 try {
36- const url = new URL ( link . href ) ;
37- url . searchParams . set ( DUB_ID_VAR , existingCookie ) ;
38- link . href = url . toString ( ) ;
39- outboundLinksUpdated . add ( link ) ;
40- } catch ( e ) { }
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 ) ;
63+
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+ }
4180 } ) ;
4281 }
4382
0 commit comments