amplitude / amplitude/Amplitude-TypeScript

`excludeReferrers` blocks ALL campaign parameter tracking instead of just referrer attribution

Abierto
#1,381 3 comentarios 0 reacciones 0 asignados Ver en GitHub
bug
Lenguaje dominante
TypeScript
Estrellas
180
Forks
68
Merge medio
3 d 1 h
PR fusionados (30 d)
29

Descripción

## Expected Behavior

When using the `excludeReferrers` configuration option in the Web Attribution Plugin, it should:
- **Exclude the specified referrer domains** from being tracked in the `referrer` and `referring_domain` attribution fields
- **Continue to track UTM parameters and click IDs** (gclid, fbclid, etc.) when they are present in the URL, regardless of the referrer

The intent of `excludeReferrers` should be to prevent self-referrals from your own domain from creating false attribution, while still capturing legitimate campaign parameters that exist in the URL.

## Current Behavior

When a referrer matches an `excludeReferrers` pattern, the plugin **completely blocks ALL campaign parameter tracking**, including:
- UTM parameters (utm_source, utm_medium, utm_campaign, etc.)
- Click IDs (gclid, fbclid, etc.)
- All other campaign attribution data

This results in missing attribution data even when valid campaign parameters are present in the URL.

## Possible Solution

The bug is in `@amplitude/analytics-client-common/lib/esm/attribution/helpers.js` in the `isNewCampaign()` function (lines 19-23):

```javascript
if (isExcludedReferrer(options.excludeReferrers, current.referring_domain)) {
logger.debug("This is not a new campaign because ".concat(current.referring_domain, " is in the exclude referrer list."));
return false; // ← BUG: Returns false immediately, blocking ALL campaign tracking
}
```

The `excludeReferrers` check happens **before** checking if there are actual new campaign parameters (line 29). This causes the function to return `false` immediately, preventing any attribution tracking.

**Suggested Fix:**

The `excludeReferrers` check should only affect the `hasNewDomain` calculation, not the entire `isNewCampaign` result. Campaign parameters should still be tracked even when the referrer is excluded. For example:

```javascript
export var isNewCampaign = function (current, previous, options, logger, isNewSession) {
// ... existing setup code ...

var hasNewCampaign = JSON.stringify(currentCampaign) !== JSON.stringify(previousCampaign);

// Only apply excludeReferrers to domain-based attribution, not parameter-based attribution
var isReferrerExcluded = isExcludedReferrer(options.excludeReferrers, current.referring_domain);
var hasNewDomain = !isReferrerExcluded &&
domainWithoutSubdomain(referring_domain || '') !== domainWithoutSubdomain(prevReferringDomain || '');

// If referrer is excluded, log it but still check for campaign parameter changes
if (isReferrerExcluded) {
logger.debug("Referrer " + current.referring_domain + " is excluded, but checking for campaign parameter changes.");
}

var result = !previous || hasNewCampaign || hasNewDomain;
// ... rest of function
}
```

## Steps to Reproduce

1. Configure the Web Attribution Plugin with `excludeReferrers` to exclude your own domain:
```javascript
import { webAttributionPlugin } from '@amplitude/plugin-web-attribution-browser';

const webAttribution = webAttributionPlugin({
excludeReferrers: [/yourdomain\.com$/]
});

amplitude.add(webAttribution);
await amplitude.init('YOUR_API_KEY');
```

2. User lands on your site from a Google Ad with campaign parameters:
- URL: `https://yourdomain.com/?utm_source=google&utm_medium=cpc&gclid=123`
- `document.referrer`: `https://www.google.com`
- **Result**: Attribution tracked correctly ✅

3. User navigates to another page internally:
- URL: `https://yourdomain.com/other-page?utm_source=google&utm_medium=cpc&gclid=123` (parameters preserved)
- `document.referrer`: `https://yourdomain.com` (matches excludeReferrers pattern)
- **Expected**: UTM parameters and gclid should still be tracked
- **Actual**: No attribution tracking happens at all ❌

4. Check Amplitude events - you'll see the campaign parameters are missing from the internal navigation events, even though they were in the URL.

### Additional Scenario: Server-Side Redirects

This bug is particularly problematic when using server-side redirects (e.g., Next.js redirects in `next.config.js`):

1. User clicks Google Ad landing on: `https://yourdomain.com/pricing?utm_source=google&utm_medium=cpc&gclid=123`
2. Server performs redirect (with query parameters preserved): `https://yourdomain.com/product/pricing?utm_source=google&utm_medium=cpc&gclid=123`
3. After redirect:
- `document.referrer`: `https://yourdomain.com/pricing` (the pre-redirect URL on your own domain)
- Current URL: `https://yourdomain.com/product/pricing?utm_source=google&utm_medium=cpc&gclid=123`
- **Expected**: UTM parameters and gclid should be tracked from the URL
- **Actual**: No attribution tracking happens because referrer matches `excludeReferrers` ❌

This means **any page that's reached via a server-side redirect loses all campaign attribution** if you use `excludeReferrers`, even on the very first page load from an external ad campaign.

**Real-world impact**: When using Google Tag Manager's Conversion Linker (which preserves gclid in cookies but not UTMs), users see `gclid` values in their analytics but no UTM parameters, because GTM re-appends gclid but Amplitude's plugin doesn't track the URL parameters when the referrer is excluded.

## Environment

- JS SDK Version:
- `@amplitude/analytics-browser@2.29.0`
- `@amplitude/plugin-web-attribution-browser@2.1.92`
- `@amplitude/analytics-client-common@2.4.11` (contains the bug)
- Installation Method: NPM
- Browser and Version: All browsers
- Next.js Version: 15.1.6

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.