|
66 | 66 | QUERY_PARAM, |
67 | 67 | ); |
68 | 68 |
|
| 69 | + // Initialize global DubAnalytics object |
| 70 | + window.DubAnalytics = window.DubAnalytics || { |
| 71 | + partner: null, |
| 72 | + discount: null, |
| 73 | + }; |
| 74 | + |
| 75 | + // Initialize dubAnalytics |
| 76 | + if (window.dubAnalytics) { |
| 77 | + const original = window.dubAnalytics; |
| 78 | + const queue = original.q || []; |
| 79 | + |
| 80 | + // Create a callable function |
| 81 | + function dubAnalytics(method, ...args) { |
| 82 | + if (method === 'ready') { |
| 83 | + dubAnalytics.ready(...args); |
| 84 | + } else if (method === 'trackClick') { |
| 85 | + dubAnalytics.trackClick(...args); |
| 86 | + } else { |
| 87 | + console.warn('[dubAnalytics] Unknown method:', method); |
| 88 | + } |
| 89 | + } |
| 90 | + |
| 91 | + // Attach properties and methods |
| 92 | + dubAnalytics.q = queue; |
| 93 | + |
| 94 | + dubAnalytics.ready = function (callback) { |
| 95 | + callback(); |
| 96 | + }; |
| 97 | + |
| 98 | + dubAnalytics.trackClick = function (...args) { |
| 99 | + trackClick(...args); |
| 100 | + }; |
| 101 | + |
| 102 | + // Replace window.dubAnalytics with the callable + augmented function |
| 103 | + window.dubAnalytics = dubAnalytics; |
| 104 | + } |
| 105 | + |
69 | 106 | // Cookie management |
70 | 107 | const cookieManager = { |
71 | 108 | get(key) { |
|
85 | 122 | }, |
86 | 123 | }; |
87 | 124 |
|
| 125 | + // Queue management |
| 126 | + const queueManager = { |
| 127 | + queue: window.dubAnalytics?.q || [], |
| 128 | + |
| 129 | + // Process specific method types (e.g., only 'ready') |
| 130 | + flush(methodFilter) { |
| 131 | + const remainingQueue = []; |
| 132 | + |
| 133 | + while (this.queue.length) { |
| 134 | + const [method, ...args] = this.queue.shift(); |
| 135 | + |
| 136 | + if (!methodFilter || methodFilter(method)) { |
| 137 | + this.process({ method, args }); |
| 138 | + } else { |
| 139 | + remainingQueue.push([method, ...args]); |
| 140 | + } |
| 141 | + } |
| 142 | + |
| 143 | + this.queue = remainingQueue; |
| 144 | + }, |
| 145 | + |
| 146 | + process({ method, args }) { |
| 147 | + if (method === 'ready') { |
| 148 | + const callback = args[0]; |
| 149 | + callback(); |
| 150 | + } else if (['trackClick'].includes(method)) { |
| 151 | + trackClick(...args); |
| 152 | + } else { |
| 153 | + console.warn('[dubAnalytics] Unknown method:', method); |
| 154 | + } |
| 155 | + }, |
| 156 | + }; |
| 157 | + |
88 | 158 | let clientClickTracked = false; |
| 159 | + |
89 | 160 | // Track click and set cookie |
90 | | - function trackClick(identifier, serverClickId) { |
91 | | - if (clientClickTracked) return; |
| 161 | + function trackClick({ domain, key }) { |
| 162 | + if (clientClickTracked) { |
| 163 | + return; |
| 164 | + } |
| 165 | + |
92 | 166 | clientClickTracked = true; |
93 | 167 |
|
| 168 | + const params = new URLSearchParams(location.search); |
| 169 | + const serverClickId = params.get(DUB_ID_VAR); |
| 170 | + |
94 | 171 | fetch(`${API_HOST}/track/click`, { |
95 | 172 | method: 'POST', |
96 | 173 | headers: { 'Content-Type': 'application/json' }, |
97 | 174 | body: JSON.stringify({ |
98 | | - domain: SHORT_DOMAIN, |
99 | | - key: identifier, |
| 175 | + domain, |
| 176 | + key, |
100 | 177 | url: window.location.href, |
101 | 178 | referrer: document.referrer, |
102 | 179 | }), |
|
106 | 183 | if (data) { |
107 | 184 | if (serverClickId && serverClickId !== data.clickId) { |
108 | 185 | console.warn( |
109 | | - `Client-tracked click ID ${data.clickId} does not match server-tracked click ID ${serverClickId}, skipping...`, |
| 186 | + `[dubAnalytics] Client-tracked click ID ${data.clickId} does not match server-tracked click ID ${serverClickId}, skipping...`, |
110 | 187 | ); |
111 | 188 | return; |
112 | 189 | } |
|
119 | 196 | partner: { |
120 | 197 | ...data.partner, |
121 | 198 | name: encodeURIComponent(data.partner.name), |
122 | | - image: encodeURIComponent(data.partner.image), |
| 199 | + image: data.partner.image |
| 200 | + ? encodeURIComponent(data.partner.image) |
| 201 | + : null, |
123 | 202 | }, |
124 | 203 | }; |
125 | 204 |
|
126 | 205 | cookieManager.set(DUB_PARTNER_COOKIE, JSON.stringify(encodedData)); |
| 206 | + |
| 207 | + DubAnalytics.partner = data.partner; |
| 208 | + DubAnalytics.discount = data.discount; |
| 209 | + |
| 210 | + queueManager.flush((method) => method === 'ready'); |
127 | 211 | } |
| 212 | + |
| 213 | + return data; |
128 | 214 | } |
129 | 215 | }); |
130 | 216 | } |
|
149 | 235 |
|
150 | 236 | // Dub Partners tracking (via query param e.g. ?via=partner_id) |
151 | 237 | if (QUERY_PARAM_VALUE && SHORT_DOMAIN && shouldSetCookie()) { |
152 | | - trackClick(QUERY_PARAM_VALUE, clickId); |
| 238 | + trackClick({ |
| 239 | + domain: SHORT_DOMAIN, |
| 240 | + key: QUERY_PARAM_VALUE, |
| 241 | + }); |
| 242 | + } |
| 243 | + |
| 244 | + // Process the queued methods |
| 245 | + queueManager.flush((method) => method === 'trackClick'); |
| 246 | + |
| 247 | + // Initialize DubAnalytics from cookie if it exists |
| 248 | + const partnerCookie = cookieManager.get(DUB_PARTNER_COOKIE); |
| 249 | + |
| 250 | + if (partnerCookie) { |
| 251 | + try { |
| 252 | + const partnerData = JSON.parse(partnerCookie); |
| 253 | + |
| 254 | + DubAnalytics.partner = partnerData.partner; |
| 255 | + DubAnalytics.discount = partnerData.discount; |
| 256 | + } catch (e) { |
| 257 | + console.error('[dubAnalytics] Failed to parse partner cookie:', e); |
| 258 | + } |
153 | 259 | } |
154 | 260 | } |
155 | 261 |
|
|
0 commit comments