File downloads Pro
Capture clicks on anchors that point to a downloadable file. Useful for lead magnets (PDFs, checklists), sample data (CSV, JSON), whitepapers, app installers, and any asset where a click is a meaningful conversion signal.
Enable
init("proj_xxx", { extensions: { downloads: true } })
// or, in React:
<Analytics projectId="proj_xxx" extensions={{ downloads: true }} />What fires
One download event per matched click:
| Property | Example | Notes |
|---|---|---|
url | https://clamp.sh/files/guide.pdf | Full resolved URL. |
filename | guide.pdf | Last path segment — use this to group by asset. |
extension | pdf | Lowercased, no leading dot. |
Default extensions
Out of the box, these extensions fire a download event:
pdf, zip, dmg, exe, msi, apk, ipa,
doc, docx, xls, xlsx, ppt, pptx, csv,
mp3, mp4, wav, mov, avi,
jpg, jpeg, png, gif, svg, webp,
tar, gz, rar, 7zHeads up: images (jpg, png, etc.) are in the default list, so a site that wraps inline images in anchor tags will fire a download event on each lightbox click. Override the list to remove image extensions if that’s noise.
Override the list
Pass your own array of extensions. The value replaces the default — it doesn’t merge. Leading dots and case are normalized for you.
init("proj_xxx", {
extensions: {
downloads: { extensions: ["pdf", "zip"] },
},
})init("proj_xxx", {
extensions: {
downloads: {
extensions: [
"pdf", "zip", "dmg", "exe",
"sketch", // custom: Sketch design files
],
},
},
})How it works
A single delegated click listener on document (capture phase) walks up to the nearest <a> via closest, resolves the href, and checks whether the pathname ends with one of the configured extensions. No listeners on individual links.
Gotchas
- Extension detection is from the pathname, not the query string. A URL like
/download?file=guide.pdfwon’t match. - Signed CDN URLs (
/guide.pdf?Signature=...) match because the extension lives in the path. The query string is ignored for matching but included in theurlproperty. - Hash-only URLs (
#guide.pdf) don’t match — no pathname. - Like outbound links, only real
<a>clicks fire. JS-driven downloads viawindow.location,BlobURLs, or programmatic anchor clicks are not captured. Usetrack("download", ...)manually for those. - Each download click costs one event against your monthly quota.
Related
- Outbound links — fires when the link host is external, even without a file extension.
- Data attributes — mark specific downloads with custom properties (source, campaign, revenue).