Skip to content

Commit 0b6f8ae

Browse files
authored
Merge pull request #63 from dubinc/wildcard-outbound-domains
Add wildcard support to outbound-domains
2 parents 031bded + 2c638d9 commit 0b6f8ae

File tree

4 files changed

+77
-3
lines changed

4 files changed

+77
-3
lines changed

apps/nextjs/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default function RootLayout({
2525
domainsConfig={{
2626
refer: 'getacme.link',
2727
site: 'getacme.link',
28-
outbound: 'example.com,other.com,sub.example.com',
28+
outbound: 'example.com,other.com,sub.example.com,*.wildcard.com',
2929
}}
3030
scriptProps={{
3131
src: DUB_ANALYTICS_SCRIPT_URL,

apps/nextjs/app/outbound/page.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@ export default function Outbound() {
1515
<a href="https://sub.example.com">Subdomain Link</a>
1616
<a href="https://other.example.com">Other Subdomain Link</a>
1717
<a href="https://www.sub.example.com">WWW Subdomain Link</a>
18+
19+
{/* Wildcard domain test links */}
20+
<a href="https://api.wildcard.com">Wildcard API Link</a>
21+
<a href="https://admin.wildcard.com">Wildcard Admin Link</a>
22+
<a href="https://deep.nested.wildcard.com">Wildcard Nested Link</a>
23+
<a href="https://wildcard.com">Wildcard Root Link</a>
24+
<a href="https://notwildcard.com">Non-Wildcard Link</a>
25+
<a href="https://www.api.wildcard.com">WWW Wildcard API Link</a>
26+
<a href="https://www.admin.wildcard.com">WWW Wildcard Admin Link</a>
1827
</div>
1928
);
2029
}

apps/nextjs/tests/outbound-domains.spec.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { DUB_ANALYTICS_SCRIPT_URL } from '@/app/constants';
21
import { test, expect } from '@playwright/test';
32

43
declare global {
@@ -27,6 +26,11 @@ test.describe('Outbound domains tracking', () => {
2726
expect(exampleHref).toContain('dub_id=test-click-id');
2827
expect(otherHref).toContain('dub_id=test-click-id');
2928
expect(unrelatedHref).not.toContain('dub_id=test-click-id');
29+
30+
// Also verify wildcard domain functionality
31+
const wildcardLink = await page.$('a[href*="api.wildcard.com"]');
32+
const wildcardHref = await wildcardLink?.getAttribute('href');
33+
expect(wildcardHref).toContain('dub_id=test-click-id');
3034
});
3135

3236
test('should handle iframe src attributes', async ({ page }) => {
@@ -149,4 +153,59 @@ test.describe('Outbound domains tracking', () => {
149153
const iframeSrc = await iframe?.getAttribute('src');
150154
expect(iframeSrc).toContain('dub_id=test-click-id');
151155
});
156+
157+
test('should handle wildcard domains correctly', async ({ page }) => {
158+
await page.goto('/outbound?dub_id=test-click-id');
159+
await page.waitForFunction(() => window._dubAnalytics !== undefined);
160+
161+
await page.waitForTimeout(1000);
162+
163+
// Test wildcard domain matching - *.wildcard.com should match all subdomains
164+
const wildcardLink = await page.$('a[href*="api.wildcard.com"]');
165+
const wildcardSubdomainLink = await page.$('a[href*="admin.wildcard.com"]');
166+
const wildcardNestedLink = await page.$(
167+
'a[href*="deep.nested.wildcard.com"]',
168+
);
169+
const wildcardRootLink = await page.$('a[href*="wildcard.com"]');
170+
171+
// Test non-wildcard domain that shouldn't match wildcard pattern
172+
const nonWildcardLink = await page.$('a[href*="notwildcard.com"]');
173+
174+
const wildcardHref = await wildcardLink?.getAttribute('href');
175+
const wildcardSubdomainHref =
176+
await wildcardSubdomainLink?.getAttribute('href');
177+
const wildcardNestedHref = await wildcardNestedLink?.getAttribute('href');
178+
const wildcardRootHref = await wildcardRootLink?.getAttribute('href');
179+
const nonWildcardHref = await nonWildcardLink?.getAttribute('href');
180+
181+
// All wildcard.com subdomains should have tracking
182+
expect(wildcardHref).toContain('dub_id=test-click-id');
183+
expect(wildcardSubdomainHref).toContain('dub_id=test-click-id');
184+
expect(wildcardNestedHref).toContain('dub_id=test-click-id');
185+
expect(wildcardRootHref).toContain('dub_id=test-click-id');
186+
187+
// Non-wildcard domain should not have tracking
188+
expect(nonWildcardHref).not.toContain('dub_id=test-click-id');
189+
});
190+
191+
test('should handle wildcard with www prefix correctly', async ({ page }) => {
192+
await page.goto('/outbound?dub_id=test-click-id');
193+
await page.waitForFunction(() => window._dubAnalytics !== undefined);
194+
195+
await page.waitForTimeout(1000);
196+
197+
// Test wildcard domain with www prefix
198+
const wwwWildcardLink = await page.$('a[href*="www.api.wildcard.com"]');
199+
const wwwWildcardSubdomainLink = await page.$(
200+
'a[href*="www.admin.wildcard.com"]',
201+
);
202+
203+
const wwwWildcardHref = await wwwWildcardLink?.getAttribute('href');
204+
const wwwWildcardSubdomainHref =
205+
await wwwWildcardSubdomainLink?.getAttribute('href');
206+
207+
// www. prefix should be ignored, so these should still match wildcard pattern
208+
expect(wwwWildcardHref).toContain('dub_id=test-click-id');
209+
expect(wwwWildcardSubdomainHref).toContain('dub_id=test-click-id');
210+
});
152211
});

packages/script/src/extensions/outbound-domains.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ const initOutboundDomains = () => {
1818
const normalizedUrlHostname = normalizeDomain(urlHostname);
1919
const normalizedDomain = normalizeDomain(domain);
2020

21-
// Exact match after removing www.
21+
// if wildcard domain, check if the url hostname ends with the apex domain
22+
if (normalizedDomain.startsWith('*.')) {
23+
const apexDomain = normalizedDomain.slice(2);
24+
return normalizedUrlHostname.endsWith(`.${apexDomain}`);
25+
}
26+
27+
// check for exact match after removing www.
2228
return normalizedUrlHostname === normalizedDomain;
2329
} catch (e) {
2430
return false;

0 commit comments

Comments
 (0)