Someone downloads your pricing PDF, your product catalog, or your whitepaper. Without tracking, you have no idea it happened — no conversion count, no attribution, no way to retarget that person who just showed high purchase intent by grabbing your spec sheet.
GA4 has a built-in “file_download” enhanced measurement event, but it’s limited. It only fires on standard <a href> links to files, and it misses plenty of real-world download patterns. This guide covers how to track all types of file downloads reliably using GTM.
What GA4’s Enhanced Measurement Already Tracks
Before building custom tracking, check if enhanced measurement is handling it:
- GA4 → Admin → Data Streams → [your stream] → Enhanced Measurement
- Look for File downloads — it should be toggled ON by default
Enhanced measurement automatically tracks clicks on links that point to files with these extensions:
pdf, xls, xlsx, doc, docx, txt, rtf, csv, exe, key, pps, ppt, pptx,
7z, pkg, rar, gz, zip, avi, mov, mp4, mpeg, wmv, midi, mp3, wav, wma
How it works: When a user clicks an <a> tag where the href ends in one of those extensions, GA4 fires a file_download event with these parameters:
file_name: The filenamefile_extension: The extensionlink_url: The full URLlink_text: The anchor text
When enhanced measurement fails:
| Scenario | Tracked? |
|---|---|
Standard <a href="/files/report.pdf"> | Yes |
JavaScript-triggered download (no <a> tag) | No |
| Download behind a form gate (submit form, then download) | No |
| Dynamic download links (blob URLs, data URIs) | No |
| Cloud storage links (Google Drive, Dropbox) | Maybe (depends on URL format) |
CDN links with query strings (report.pdf?token=abc) | Yes (enhanced measurement strips query params) |
| Button that programmatically triggers download | No |
If enhanced measurement covers your use case, you’re done. If not, read on.
Method 1: Link Click Trigger (Most Common)
This handles the 80% case — users click a link that points to a downloadable file.
Step 1: Enable Click Variables
- GTM → Variables → Configure Built-In Variables
- Enable:
Click URL,Click Text,Click Element,Click Classes
Step 2: Create the Trigger
- GTM → Triggers → New
- Trigger type: Click - Just Links
- This trigger fires on: Some Link Clicks
- Condition:
Click URL → matches RegEx → \.(pdf|csv|xlsx|xls|docx|doc|zip|pptx|ppt)(\?.*)?$
This regex matches any link URL ending in common file extensions, with or without query parameters.
Make it case-insensitive: Select “matches RegEx (ignore case)” to catch .PDF and .Pdf variants.
Step 3: Create the GA4 Event Tag
- GTM → Tags → New
- Tag type: Google Analytics: GA4 Event
- Configuration tag: Your GA4 configuration
- Event name:
file_download - Event parameters:
| Parameter | Value |
|---|---|
file_name | {{Click URL}} — or create a custom variable to extract just the filename |
file_extension | Create a Custom JavaScript variable (see below) |
link_text | {{Click Text}} |
link_url | {{Click URL}} |
- Trigger: The link click trigger from Step 2
Extract File Extension (Custom Variable)
Create a Custom JavaScript variable called “File Extension from Click URL”:
function() {
var url = {{Click URL}};
if (!url) return '';
var match = url.match(/\.([a-zA-Z0-9]+)(\?.*)?$/);
return match ? match[1].toLowerCase() : '';
}
Extract Filename (Custom Variable)
Create a Custom JavaScript variable called “Filename from Click URL”:
function() {
var url = {{Click URL}};
if (!url) return '';
// Remove query string and hash
var clean = url.split('?')[0].split('#')[0];
// Get last path segment
var parts = clean.split('/');
return parts[parts.length - 1] || '';
}
Method 2: JavaScript-Triggered Downloads
Some sites generate downloads via JavaScript — no <a href> link exists. Common patterns:
- “Export to CSV” buttons in web apps
- “Generate Report” buttons that create PDFs on the fly
- Download buttons that fetch from an API and trigger a browser download
Option A: Data Layer Push
If you control the download code, push a data layer event when the download triggers:
function downloadReport(reportId) {
// Your existing download logic
fetch(`/api/reports/${reportId}/download`)
.then(response => response.blob())
.then(blob => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `report-${reportId}.pdf`;
a.click();
// Track the download
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: 'file_download',
file_name: `report-${reportId}.pdf`,
file_extension: 'pdf',
download_method: 'generated'
});
});
}
In GTM, create a Custom Event trigger for file_download and a tag that sends the parameters to GA4.
Option B: Click Listener on Download Buttons
If the download buttons have identifiable classes or IDs:
- Create a trigger: Click - All Elements
- Condition:
Click Classes → contains → download-btn(or whatever class identifies download buttons) - Fire your GA4 event tag
Option C: MutationObserver (Last Resort)
For sites where downloads happen through complex UI frameworks and you can’t modify the code:
<script>
// Watch for dynamically created download links
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
mutation.addedNodes.forEach(function(node) {
if (node.tagName === 'A' && node.download) {
window.dataLayer.push({
event: 'file_download',
file_name: node.download || node.href,
download_method: 'dynamic_link'
});
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
</script>
Use this sparingly — it adds overhead to every DOM change.
Method 3: Cloud Storage Downloads
Downloads hosted on Google Drive, Dropbox, S3, or other cloud storage have URLs that don’t end in file extensions:
https://drive.google.com/file/d/1abc.../view
https://www.dropbox.com/s/abc123/report.pdf?dl=1
https://s3.amazonaws.com/bucket/reports/q4-2026.pdf
Track Cloud Storage Links
Modify the trigger regex to include cloud storage domains:
(\.(pdf|csv|xlsx|zip)(\?.*)?$)|(drive\.google\.com/file)|(dropbox\.com/s/)|(s3\.amazonaws\.com)
Or create a separate trigger specifically for cloud links:
Click URL → matches RegEx → (drive\.google\.com|dropbox\.com|s3\.amazonaws\.com)
Then extract the link text or filename from surrounding context:
function() {
var url = {{Click URL}};
// Try to extract filename from URL
var match = url.match(/\/([^\/\?]+\.[a-zA-Z]{2,4})(\?.*)?$/);
if (match) return match[1];
// Fall back to click text
return {{Click Text}} || 'unknown-file';
}
Sending Download Data to GA4
Standard Event Parameters
Send these with every file_download event:
| Parameter | Value | Purpose |
|---|---|---|
file_name | Filename | Identify which file |
file_extension | Extension (pdf, csv, etc.) | Filter by file type |
link_url | Full URL | Debug and verify |
link_text | Anchor text | Context |
Custom Parameters for Business Context
Add parameters that help you understand download intent:
| Parameter | Example Value | Why |
|---|---|---|
file_category | ”pricing”, “case-study”, “spec-sheet” | Segment by content type |
page_section | ”resources”, “product-page”, “blog” | Where on the site |
gated | ”true” / “false” | Was it behind a form? |
Mark Downloads as Conversions
If file downloads represent meaningful business actions (pricing PDF, demo request):
- GA4 → Admin → Events
- Find
file_download - Toggle Mark as conversion
Or create a more specific event (like pricing_pdf_download) and mark only that as a conversion.
Tracking Gated Downloads
Gated downloads (fill a form to get the PDF) are a two-step process:
- Track the form submission — see our GTM form tracking guide
- Track the actual download — using the methods above
- Connect them — pass the lead’s email/ID as a parameter in both events
// After form submission, when download link is revealed
window.dataLayer.push({
event: 'gated_download',
file_name: 'industry-report-2026.pdf',
file_extension: 'pdf',
lead_source: 'resource-center',
form_id: 'whitepaper-gate'
});
Testing
GTM Preview Mode
- Enable Preview Mode
- Click a download link on your site
- Check the Tags panel — your download tracking tag should show as “Fired”
- Check the Variables tab — verify
Click URL,Click Text, and your custom variables show correct values
GA4 DebugView
- Enable GA4 Debug Mode (via GTM Preview or browser extension)
- GA4 → Admin → DebugView
- Click a download link
- Watch for the
file_downloadevent - Click on it to verify parameters
GA4 Realtime Report
After clicking a download link, check GA4 → Realtime → Event count for file_download.
Common Issues
| Problem | Cause | Fix |
|---|---|---|
| Downloads not tracking | Enhanced measurement disabled, no GTM trigger | Enable enhanced measurement OR create click trigger |
| Wrong file extension captured | Query string confusing the regex | Use (\?.*)?$ in your regex to strip query params |
(not set) as filename | {{Click URL}} is empty for JS-triggered downloads | Use data layer push instead |
| Duplicate download events | Both enhanced measurement AND GTM tracking the same click | Disable enhanced measurement file downloads if using custom GTM tracking |
| Cloud storage downloads not tracking | URL doesn’t match file extension regex | Add cloud storage domain patterns to trigger |
Checklist
- Enhanced measurement file downloads reviewed (on or off, but not duplicating custom tracking)
- Link click trigger created with file extension regex
- GA4 event tag configured with file_name, file_extension, link_url
- JavaScript-triggered downloads tracked via data layer push
- Cloud storage links handled (if applicable)
- Custom variables for filename and extension extraction working
- Download events visible in GA4 DebugView
- Key downloads marked as conversions (if business-relevant)
File downloads are one of the clearest intent signals on your site. Someone downloading your pricing PDF is further along the funnel than someone reading your blog. Track it, attribute it, and retarget based on it.
Want to know if your download tracking is working correctly? Run a free scan — we check your GTM configuration, event tracking, and GA4 integration.