When tracking events fail to fire on your Umbraco site, systematic debugging is essential. This guide covers .NET-specific debugging, browser DevTools usage, IIS configuration issues, and Umbraco-specific troubleshooting for GA4, GTM, and Meta Pixel.
Common Symptoms
- Events not appearing in Google Analytics Realtime
- GTM Preview Mode shows no tags firing
- Meta Pixel Helper shows no events
- Browser console shows tracking errors
- Data layer not populated
- Tracking scripts not loading
Debugging Strategy
Step 1: Verify Tracking Code Installation
Check Razor view includes tracking:
@* In Master.cshtml or _Layout.cshtml *@
<!DOCTYPE html>
<html>
<head>
@* Should include GTM or GA4 *@
@await Html.PartialAsync("~/Views/Partials/Analytics/GoogleTagManager.cshtml")
</head>
<body>
@* Should include GTM noscript *@
@await Html.PartialAsync("~/Views/Partials/Analytics/GoogleTagManagerNoScript.cshtml")
@RenderBody()
</body>
</html>
Verify in browser:
- Open your Umbraco site
- View page source (Ctrl+U)
- Search for tracking IDs:
- GA4:
G-XXXXXXXXXX - GTM:
GTM-XXXXXXX - Meta Pixel: Your 16-digit Pixel ID
- GA4:
- Verify scripts are present
Step 2: Check Browser Console
- Open DevTools (F12)
- Click Console tab
- Look for JavaScript errors
- Common errors:
Uncaught ReferenceError: gtag is not defined Uncaught ReferenceError: dataLayer is not defined Uncaught ReferenceError: fbq is not defined
Step 3: Verify Network Requests
- Open DevTools → Network tab
- Filter by
google-analytics.comorgoogletagmanager.com - Reload page
- Verify requests are sent:
- GA4:
collectendpoint - GTM:
gtm.jsscript - Meta Pixel:
facebook.com/trendpoint
- GA4:
GA4-Specific Debugging
Check GA4 Installation
Verify gtag function exists:
<script>
// Debug GA4
window.addEventListener('load', function() {
if (typeof gtag === 'function') {
console.log('✓ GA4 gtag function exists');
// Check data layer
console.log('Data Layer:', window.dataLayer);
} else {
console.error('✗ GA4 gtag function not found');
}
});
</script>
Enable GA4 Debug Mode
In Razor view:
@inject Microsoft.Extensions.Hosting.IHostEnvironment HostEnvironment
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXXXXXXXXX', {
@if (HostEnvironment.IsDevelopment())
{
<text>
'debug_mode': true,
</text>
}
'send_page_view': true
});
@if (HostEnvironment.IsDevelopment())
{
<text>
// Log all gtag calls
var originalGtag = window.gtag;
window.gtag = function() {
console.log('GA4 Event:', arguments);
return originalGtag.apply(this, arguments);
};
</text>
}
</script>
Test GA4 Events
Manual event firing:
// In browser console
gtag('event', 'test_event', {
'event_category': 'test',
'event_label': 'manual_test'
});
Then check Google Analytics → Realtime → Events for test_event.
Common GA4 Issues
Issue: gtag not defined
Cause: Script not loaded or blocked Solution:
<script>
// Wait for gtag to load
function waitForGtag(callback) {
if (typeof gtag !== 'undefined') {
callback();
} else {
setTimeout(function() { waitForGtag(callback); }, 100);
}
}
waitForGtag(function() {
console.log('GA4 ready');
gtag('event', 'page_view');
});
</script>
Issue: Events not showing in Realtime
Cause: Wrong Measurement ID or property Solution:
@inject IConfiguration Configuration
@{
var gaId = Configuration["Analytics:GoogleAnalytics:MeasurementId"];
if (string.IsNullOrEmpty(gaId))
{
throw new Exception("GA4 Measurement ID not configured");
}
}
<script>
console.log('Using GA4 ID:', '@gaId');
gtag('config', '@gaId');
</script>
GTM-Specific Debugging
Check GTM Installation
Verify dataLayer exists:
// In browser console
console.log(dataLayer);
console.log(google_tag_manager);
Should output arrays/objects, not undefined.
Use GTM Preview Mode
- Log in to Google Tag Manager
- Click Preview button
- Enter your Umbraco site URL
- GTM Debug panel opens
- Navigate site and verify:
- Tags fire correctly
- Variables populate
- Triggers activate
Debug Data Layer
Log all data layer pushes:
@inject Microsoft.Extensions.Hosting.IHostEnvironment HostEnvironment
@if (HostEnvironment.IsDevelopment())
{
<script>
// Initialize data layer with logging
window.dataLayer = window.dataLayer || [];
var originalPush = window.dataLayer.push;
window.dataLayer.push = function() {
console.log('Data Layer Push:', arguments);
return originalPush.apply(window.dataLayer, arguments);
};
</script>
}
Common GTM Issues
Issue: GTM container not loading
Cause: Incorrect Container ID or CSP blocking Solution:
<!-- In Web.config -->
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy"
value="script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; img-src 'self' https://www.google-analytics.com;" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
Issue: Data layer not initialized before GTM
Cause: Wrong script order Solution:
<!-- Initialize data layer FIRST -->
<script>
window.dataLayer = window.dataLayer || [];
dataLayer.push({
'pageType': '@Model?.ContentType.Alias'
});
</script>
<!-- THEN load GTM -->
<script>
(function(w,d,s,l,i){/* GTM script */})(window,document,'script','dataLayer','GTM-XXXXXXX');
</script>
Meta Pixel Debugging
Check Meta Pixel Installation
Verify fbq function:
// In browser console
console.log(typeof fbq);
// Should output: "function"
console.log(fbq.version);
// Should output: "2.0"
Use Meta Pixel Helper
- Install Meta Pixel Helper Chrome extension
- Navigate to your Umbraco site
- Click extension icon
- Verify:
- Pixel detected
- Events firing
- No errors
Debug Meta Pixel Events
Enable console logging:
@inject Microsoft.Extensions.Hosting.IHostEnvironment HostEnvironment
<script>
!function(f,b,e,v,n,t,s) {/* Meta Pixel base code */}(window, document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'YOUR_PIXEL_ID');
@if (HostEnvironment.IsDevelopment())
{
<text>
// Log all fbq calls
var originalFbq = window.fbq;
window.fbq = function() {
console.log('Meta Pixel Event:', arguments);
return originalFbq.apply(this, arguments);
};
</text>
}
fbq('track', 'PageView');
</script>
Common Meta Pixel Issues
Issue: fbq not defined
Cause: Script blocked by ad blocker or CSP Solution:
<script>
// Check if fbq exists before calling
if (typeof fbq === 'function') {
fbq('track', 'PageView');
} else {
console.warn('Meta Pixel blocked or not loaded');
}
</script>
Umbraco-Specific Issues
Umbraco Cache Preventing Updates
Issue: Code changes not reflected Solution:
# Clear Umbraco cache
Remove-Item -Path "App_Data\TEMP\*" -Recurse -Force
Remove-Item -Path "App_Data\NuCache\*" -Recurse -Force
# Rebuild Examine indexes
# Navigate to Umbraco Backoffice → Settings → Examine Management → Rebuild all indexes
Or via code:
using Umbraco.Cms.Core.Cache;
public class CacheClearer
{
private readonly AppCaches _appCaches;
public CacheClearer(AppCaches appCaches)
{
_appCaches = appCaches;
}
public void ClearAll()
{
_appCaches.RuntimeCache.Clear();
_appCaches.RequestCache.Clear();
}
}
Partial View Not Rendering
Issue: Tracking partial not included Debug:
@* Add debug output *@
@{
var partialPath = "~/Views/Partials/Analytics/GoogleTagManager.cshtml";
}
<!-- Attempting to render: @partialPath -->
@try
{
@await Html.PartialAsync(partialPath)
<!-- ✓ Partial rendered successfully -->
}
catch (Exception ex)
{
<!-- ✗ Error rendering partial: @ex.Message -->
}
Configuration Not Loading
Issue: appsettings.json values not accessible Debug:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
public class ConfigDebugger
{
private readonly IConfiguration _configuration;
private readonly ILogger<ConfigDebugger> _logger;
public ConfigDebugger(IConfiguration configuration, ILogger<ConfigDebugger> logger)
{
_configuration = configuration;
_logger = logger;
}
public void LogConfiguration()
{
var gaId = _configuration["Analytics:GoogleAnalytics:MeasurementId"];
var gtmId = _configuration["Analytics:GoogleTagManager:ContainerId"];
_logger.LogInformation($"GA4 ID: {gaId ?? "NOT SET"}");
_logger.LogInformation($"GTM ID: {gtmId ?? "NOT SET"}");
}
}
In Razor:
@inject IConfiguration Configuration
@inject ILogger<RazorPage> Logger
@{
var gaId = Configuration["Analytics:GoogleAnalytics:MeasurementId"];
if (string.IsNullOrEmpty(gaId))
{
Logger.LogWarning("GA4 Measurement ID not configured in appsettings.json");
}
else
{
Logger.LogInformation($"Using GA4 ID: {gaId}");
}
}
IIS-Specific Issues
URL Rewrite Interfering
Issue: IIS URL Rewrite blocking tracking scripts Check Web.config:
<configuration>
<system.webServer>
<rewrite>
<rules>
<!-- Ensure tracking scripts not blocked -->
<rule name="Allow Tracking Scripts" stopProcessing="true">
<match url="^(gtag|gtm|fbevents)\.js$" />
<action type="None" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
HTTPS/SSL Issues
Issue: Mixed content blocking tracking on HTTPS Solution:
<configuration>
<system.webServer>
<rewrite>
<outboundRules>
<rule name="Upgrade tracking to HTTPS">
<match filterByTags="Script"
pattern="http://(www\.google-analytics\.com|www\.googletagmanager\.com|connect\.facebook\.net)" />
<action type="Rewrite"
value="https://{R:1}" />
</rule>
</outboundRules>
</rewrite>
</system.webServer>
</configuration>
Application Pool Recycling
Issue: Tracking breaks after app pool recycle Solution:
<!-- In Web.config -->
<configuration>
<system.webServer>
<serverRuntime enabled="true" />
</system.webServer>
<system.web>
<compilation debug="false" targetFramework="net6.0" />
<httpRuntime targetFramework="net6.0" enableVersionHeader="false" />
</system.web>
</configuration>
Debugging Tools and Extensions
Browser Extensions
- Google Tag Assistant - Verify GA4 and GTM
- Meta Pixel Helper - Debug Meta Pixel
- Web Vitals - Monitor performance
- EditThisCookie - Check tracking cookies
.NET Debugging
Add comprehensive logging:
using Microsoft.Extensions.Logging;
public class TrackingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<TrackingMiddleware> _logger;
public TrackingMiddleware(RequestDelegate next, ILogger<TrackingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
_logger.LogInformation($"Request URL: {context.Request.Path}");
_logger.LogInformation($"User Agent: {context.Request.Headers["User-Agent"]}");
await _next(context);
}
}
Network Inspection
Check tracking requests:
// In browser console
performance.getEntriesByType('resource')
.filter(r => r.name.includes('google-analytics') ||
r.name.includes('googletagmanager') ||
r.name.includes('facebook'))
.forEach(r => console.log(r.name, r.responseStatus));
Systematic Debugging Checklist
- Tracking code present in page source
- No JavaScript errors in console
- Network requests to tracking domains successful
- Tracking functions (gtag/fbq) defined
- Data layer initialized (for GTM)
- Configuration values loaded correctly
- Umbraco cache cleared
- IIS/Web.config not blocking scripts
- CSP headers allow tracking domains
- HTTPS/SSL configured correctly
- Ad blockers disabled for testing
- Cookies enabled in browser
Next Steps
- GA4 Setup - Configure Google Analytics
- GTM Setup - Install Google Tag Manager
- Meta Pixel Setup - Configure Meta Pixel