[analytics-core] getQueryParams does not decode `+` as space and truncates values containing `=`

Aperta Adatta ai principianti
#2,179 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
82/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
javascript, typescript
Ambito
analytics

Direzione di ricerca

Inizia da packages/analytics-core/src/query-params.ts, dove getQueryParams suddivide ogni coppia con split('=', 2) e decodifica tramite tryDecodeURIComponent. CampaignParser, nello stesso pacchetto, usa il suo output, quindi controllalo anche. È completato quando la query string d'esempio della issue produce utm_source 'news letter', utm_term 'running shoes', utm_content 'a=b=c' e gclid 'abc==', con un test che lo copre.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

Expected Behavior

getQueryParams() and CampaignParser should decode + as a space per application/x-www-form-urlencoded (matching URLSearchParams and legacy amplitude-js's utils.getQueryParam) and preserve = characters inside parameter values.

For ?utm_source=news+letter&utm_term=running+shoes&utm_content=a%3Db=c&gclid=abc==, the parsed parameters should be:

{
  utm_source: 'news letter',
  utm_term: 'running shoes',
  utm_content: 'a=b=c',
  gclid: 'abc=='
}

Current Behavior

In packages/analytics-core/src/query-params.ts, getQueryParams() splits each pair with curr.split('=', 2) and decodes with decodeURIComponent() directly:

  1. In JavaScript, String.prototype.split('=', 2) splits on every = and returns only the first two elements, discarding everything from the second = onward ('gclid=abc=='.split('=', 2) returns ['gclid', 'abc']).
  2. decodeURIComponent() leaves + as a literal +, so ?utm_term=running+shoes and ?utm_term=running%20shoes are recorded as two distinct campaign terms.

Because CampaignParser and analytics-browser call getQueryParams(), default init() records the unparsed + and truncated values in both $identify (initial_utm_*, utm_*, initial_gclid, gclid) and [Amplitude] Page Viewed event properties.

Possible Solution

Split on the first = using indexOf('=') instead of split('=', 2), and replace + with ' ' before calling decodeURIComponent() in tryDecodeURIComponent:

const eqIndex = curr.indexOf('=');
if (eqIndex === -1) {
  return acc;
}
const key = tryDecodeURIComponent(curr.slice(0, eqIndex).replace(/\+/g, ' '));
const value = tryDecodeURIComponent(curr.slice(eqIndex + 1).replace(/\+/g, ' '));

Steps to Reproduce

  1. Install @amplitude/[email protected]:
    npm i @amplitude/[email protected]
    
  2. Run:
    node --input-type=module <<'EOF'
    import { CampaignParser, getQueryParams } from "@amplitude/analytics-core";
    
    const search = "?utm_source=news+letter&utm_term=running+shoes&utm_content=a%3Db=c&gclid=abc==";
    globalThis.location = { search, href: "https://example.com/" + search, hostname: "example.com" };
    
    console.log(getQueryParams());
    const c = await new CampaignParser().parse();
    console.log(c.utm_source, "|", c.utm_term, "|", c.utm_content, "|", c.gclid);
    EOF
    
  3. Actual output:
    {
      utm_source: 'news+letter',
      utm_term: 'running+shoes',
      utm_content: 'a=b',
      gclid: 'abc'
    }
    news+letter | running+shoes | a=b | abc
    

Environment

  • JS SDK Version: @amplitude/[email protected], @amplitude/[email protected], and main (5b445aa)
  • Installation Method: npm
  • Browser and Version: Node.js v26.13.0 (also affects all browsers via @amplitude/analytics-browser)

Credit: https://ucsbplse.github.io/

Lingua principale
TypeScript
Stelle
181
Fork
66
Merge medio
2g 21h
PR unite (30g)
41

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di amplitude/Amplitude-TypeScript

Tutte le issue di amplitude/Amplitude-TypeScript

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.