A Rakuten (LinkShare) conversion hit is one long line of percent signs, pipes and digits. The hit holds exactly what the network received about the order: which products, how many, and for how much.

This guide shows how to read one in about 30 seconds, using a real order hit with the brand, product names and order number replaced by placeholders. It is written for tracking and analytics consultants and for e-commerce teams who have to answer the question “why does the affiliate report not match our basket?”.

Why the URL looks unreadable: percent-encoding, not HTML entities

The hit is a URL, so its special characters are percent-encoded. Each byte that cannot appear as is becomes a percent sign followed by two hexadecimal digits. MDN describes encodeURIComponent() as replacing characters with one to four escape sequences that represent their UTF-8 encoding, and decodeURIComponent() reverses it.

HTML entities are a different mechanism with a different job. They exist inside HTML documents and start with an ampersand: a named reference such as & or a numeric one such as '. The same character has a different spelling in each system.

What you seeWhere it livesWhat it means
%20URL (percent-encoding)a space (byte 0x20)
%3EURLthe character >
%27URLan apostrophe
%C2%A0URLa non-breaking space: two UTF-8 bytes, C2 and A0
&HTML (named reference)an ampersand
'HTML (numeric reference)an apostrophe, written as its code point
 HTML (named reference)a non-breaking space

One more detail matters for pixel URLs. URLSearchParams reads a plus sign in a query string as a space, so a value containing a real plus sign has to be sent as %2B. And decodeURIComponent() throws a URIError when a percent sign is not followed by two hexadecimal digits, so a truncated hit can break a decoder.

Step 1: split the query parameters

Cut the URL at the question mark, then at each ampersand. The hit in this example goes to track.linksynergy.com/ep and carries these parameters:

Tealium’s guide says the Rakuten library builds skulist, namelist, qlist and amtlist from the order’s line items. Each product therefore appears at the same position in every list, which is what makes the alignment in step 2 possible.

Step 2: align the lists into one row per product

The first value of every list belongs to the first product, the second value to the second product, and so on. The script below does the alignment. It splits each list on the pipe character before decoding, so that an encoded pipe inside a product name does not create a false column. It then reports any list with a different length and any empty amount.

function decodeHit(hitUrl) {
  const dec = (s) => decodeURIComponent(s.replace(/\+/g, " "));
  const raw = Object.fromEntries(
    new URL(hitUrl).search.slice(1).split("&").map((pair) => {
      const i = pair.indexOf("=");
      return [pair.slice(0, i), pair.slice(i + 1)];
    })
  );
  const listKeys = ["skulist", "qlist", "amtlist", "namelist", "catlist", "brandlist"];
  const columns = {};
  for (const k of listKeys) {
    columns[k] = (raw[k] ?? "").split("|").map(dec);
  }
  const n = Math.max(...Object.values(columns).map((c) => c.length));
  const rows = Array.from({ length: n }, (_, i) =>
    Object.fromEntries(listKeys.map((k) => [k, columns[k][i] ?? ""]))
  );
  const issues = [];
  for (const k of listKeys) {
    if (columns[k].length !== n) issues.push(`${k}: ${columns[k].length} values, expected ${n}`);
  }
  rows.forEach((r, i) => {
    if (r.amtlist === "") issues.push(`row ${i + 1} (${r.skulist}): empty amtlist`);
  });
  return { rows, issues };
}

const { rows, issues } = decodeHit(location.href); // or paste the hit URL as a string
console.table(rows);
console.log(issues);

Run on the example hit, it gives this table:

#skulistqlistamtlistnamelistcatlistbrandlist
18009895521544Product ACategory ABrand
2800811831550Product BCategory ABrand
3800820771(empty)Product CSamplesBrand
4800830791(empty)Product DSamplesBrand
5801242571(empty)Product ESamplesBrand
68010451411540Product FCategory ABrand

What the table shows

The order has six lines, but amtlist is empty for three of them (rows 3 to 5), and those three lines sit in the category “Samples”. They are most likely free samples added to the basket at a price of zero. Two things follow from that.

First, the network never receives an amount for those lines. That may be exactly what you want, but it should be a decision, not an accident of how the tag reads the basket.

Second, the amounts are not in the units you see in the shop. MetaRouter’s Rakuten documentation states that amtlist is expressed in cents, multiplied by 100 for most currencies and not for Japanese yen. On that basis the three priced lines add up to 1544 + 550 + 1540 = 3634, or 36.34 GBP, while the discount fields read 18.72. I could not find a Rakuten page that states the unit or explains how empty entries are treated, so confirm both with your Rakuten account manager before you rely on them. Also check whether 1544 on row 1, which has a quantity of 2, is a line total or a unit price.

MetaRouter also documents a convention where a discount travels as an extra line with the SKU “Discount”. This hit sends the discount in separate parameters instead, with no such line. Whether that is correct for your program is a question for the network.

A checklist for any affiliate conversion hit

CheckWhat to look for
List lengthsAll six lists have the same number of values as skulist.
Empty amountsEvery empty amtlist slot has a known reason (free sample, gift, bundle component).
Quantity and amountThe amount is the line total or the unit price, consistently, on every row.
TotalsThe sum of amtlist, minus the discount, matches the order total in your back office.
Unitsamtlist and the discount parameters use the units the documentation expects for the currency.
EncodingNo value shows %25 followed by two hex digits, which would mean it was encoded twice.

Audit it on your own site

Open your browser’s network panel, filter on the network’s domain, place a test order that includes a free item and copy the request URL. Run the script on it and compare the output with the order confirmation. Repeat with a discount code, with a multi-quantity line and with a product whose name contains an accent or an apostrophe, since those are the cases where encoding goes wrong.

If you would rather not paste code, the free URL decoder on this site splits and decodes a hit in the browser.

Sources

Not sure your own tracking is right?

Book a call Or start with the free analytics audit →