Episerver Troubleshooting: Common Issues and Fixes | OpsBlu Docs

Episerver Troubleshooting: Common Issues and Fixes

Comprehensive troubleshooting guide for common issues with Episerver CMS and Commerce (Optimizely)

Common issues and solutions for Episerver (now Optimizely) CMS and Commerce implementations, including performance, tracking, and integration problems.

Quick Diagnosis

Performance Issues

Symptom Likely Cause Solution
Slow page loads Large scripts blocking render Optimize LCP
Content jumping Async content loading Fix CLS
High server response time Database queries, caching Check caching configuration
Large bundle sizes Unoptimized assets Enable bundling/minification

Tracking Issues

Symptom Likely Cause Solution
No tracking in production Edit mode check incorrect Verify PageIsInEditMode logic
Events not firing JavaScript errors Check browser console
Duplicate events Multiple implementations Events Not Firing
Missing ecommerce data Data layer incorrect Check data layer structure

Edit Mode Issues

Symptom Likely Cause Solution
Tracking in edit mode Missing edit mode check Add PageIsInEditMode check
Scripts break editor Conflicting JavaScript Wrap in edit mode check
Content blocks not editable JavaScript interference Disable scripts in edit mode

Performance Troubleshooting

Core Web Vitals

Episerver-specific guidance for optimizing Core Web Vitals:

Largest Contentful Paint (LCP)

Target: < 2.5 seconds

Common Episerver LCP issues:

  • Large hero images from Media Library
  • Render-blocking scripts in <head>
  • Slow server response times
  • Unoptimized content delivery

View LCP Troubleshooting Guide

Cumulative Layout Shift (CLS)

Target: < 0.1

Common Episerver CLS issues:

  • Content areas loading asynchronously
  • Block rendering causing shifts
  • Visitor group personalization
  • Dynamic content injection

View CLS Troubleshooting Guide

First Input Delay (FID) / Interaction to Next Paint (INP)

Target: FID < 100ms, INP < 200ms

Common causes:

  • Heavy JavaScript from tracking scripts
  • Large Episerver Forms
  • Edit mode JavaScript loading in view mode
  • Unoptimized event handlers

Page Load Performance

Slow Server Response Time

Diagnosis:

// Add timing header to see server processing time
public class PerformanceHeaderFilter : ActionFilterAttribute
{
    private Stopwatch _stopwatch;

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        _stopwatch = Stopwatch.StartNew();
    }

    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        _stopwatch.Stop();
        filterContext.HttpContext.Response.Headers.Add(
            "X-Server-Timing",
            $"app;dur={_stopwatch.ElapsedMilliseconds}"
        );
    }
}

Common Solutions:

  1. Enable output caching
  2. Optimize database queries
  3. Use content delivery cache
  4. Implement Redis caching
  5. Review Find queries

Render-Blocking Resources

Check for blocking scripts:

<!-- BAD: Blocking script in head -->
<head>
    <script src="/Scripts/large-library.js"></script>
</head>

<!-- GOOD: Async or deferred -->
<head>
    <script src="/Scripts/large-library.js" defer></script>
</head>

Episerver Client Resources:

// Load scripts at footer (non-blocking)
context.Locate.Advanced.GetInstance<IClientResourceService>()
    .RequireScript("/Scripts/app.js")
    .AtFooter();

Asset Optimization

Bundling and Minification

Enable in CMS 12+:

// Startup.cs
public void Configure(IApplicationBuilder app)
{
    app.UseStaticFiles(new StaticFileOptions
    { =>
        {
            ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=31536000");
        }
    });

    // Enable response compression
    app.UseResponseCompression();
}

For CMS 11:

<!-- web.config -->
<system.web>
  <compilation debug="false" targetFramework="4.7.2" />
</system.web>

Image Optimization

Use Episerver ImageResizer:

@{
    var imageUrl = Url.ContentUrl(Model.Image);
    var optimizedUrl = $"{imageUrl}?width=800&quality=80&format=webp";
}

<img src="@optimizedUrl"
     alt="@Model.ImageAlt"
     width="800"
     height="600"
     loading="lazy" />

Tracking Troubleshooting

Analytics Not Working

Scripts Not Loading

Check 1: Edit Mode Detection

// Correct way (CMS 12+)
var isEditMode = EPiServer.Editor.PageEditing.PageIsInEditMode;

// Correct way (CMS 11)
var isEditMode = PageEditing.PageIsInEditMode(HttpContext);

Check 2: Content Security Policy

<!-- web.config -->
<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Content-Security-Policy"
           value="script-src 'self' 'unsafe-inline' https://*.googletagmanager.com https://*.google-analytics.com https://connect.facebook.net;" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

Check 3: Browser Console

  • Open DevTools (F12)
  • Check Console tab for errors
  • Look for "Refused to load" or "Refused to execute"

Events Not Firing

View Events Not Firing Guide

Common causes:

  • JavaScript errors
  • Incorrect event syntax
  • GTM trigger not configured
  • Ad blockers (expected behavior)

Duplicate Events

Cause: Multiple tracking implementations

Solution: Search codebase

# Search for GA4
grep -r "gtag('config'" .
grep -r "googletagmanager.com/gtag" .

# Search for Meta Pixel
grep -r "fbq('init'" .
grep -r "fbevents.js" .

# Search for GTM
grep -r "googletagmanager.com/gtm.js" .

Ecommerce Tracking Issues

Missing Purchase Data

Check 1: Order Confirmation Loading

var orderId = RouteData.Values["orderNumber"]?.ToString();
if (string.IsNullOrEmpty(orderId))
{
    // Order ID not found - check routing
}

var order = _orderRepository.Load<IPurchaseOrder>(orderId);
if (order == null)
{
    // Order not found - check order loading
}

Check 2: Duplicate Prevention Ensure you're not preventing first-time tracking:

@if (order != null && HttpContext.Items["OrderTracked"] == null)
{
    <!-- Track purchase -->
}

Incorrect Product Data

Check data layer structure:

// Browser console
console.log(window.dataLayer);

// Verify ecommerce object
window.dataLayer.forEach((item, index) => {
  if (item.ecommerce) {
    console.log(`Item ${index}:`, item.ecommerce);
  }
});

Edit Mode vs. View Mode

Tracking in Edit Mode

Problem: Analytics fire when editing content

Solution: Add edit mode checks

@{
    var isEditMode = EPiServer.Editor.PageEditing.PageIsInEditMode;
}

@if (!isEditMode)
{
    <!-- Tracking scripts here -->
}

Preview Mode Considerations

Decision: Should tracking fire in preview mode?

Option 1: Disable in preview

var isPreviewMode = EPiServer.Web.ContextMode.Current == EPiServer.Web.ContextMode.Preview;
if (!isEditMode && !isPreviewMode)
{
    // Load tracking
}

Option 2: Enable in preview (to test)

if (!isEditMode)
{
    // Load tracking (fires in preview)
}

Scripts Breaking Editor

Problem: JavaScript interferes with edit mode

Solutions:

  1. Wrap all scripts in edit mode check
  2. Use edit mode-aware event handlers
  3. Check PageEditing.PageIsInEditMode before DOM manipulation

Multi-Site Issues

Wrong Tracking ID

Problem: Site A uses Site B's tracking ID

Diagnosis:

// Log current site info
var currentSite = SiteDefinition.Current;
_logger.Information($"Site: {currentSite.Name}, Host: {currentSite.SiteUrl.Host}");

Solution: Use site-based configuration

public static string GetGATrackingId(this SiteDefinition site)
{
    return site.SiteUrl.Host switch
    {
        "www.site1.com" => "G-SITE1XXXX",
        "www.site2.com" => "G-SITE2XXXX",
        _ => null
    };
}

Multi-Language Issues

Problem: Language not tracked correctly

Solution: Include language in data layer

@{
    var language = (Model as ILocalizable)?.Language?.Name ?? "en";
}

<script>
  window.dataLayer = window.dataLayer || [];
  window.dataLayer.push({
    'language': '@language',
    'pageUrl': '@Url.ContentUrl(Model.ContentLink)'
  });
</script>

Content Delivery API (Headless)

Tracking IDs Not Available

Problem: Frontend doesn't have tracking IDs

Solution: Return in API responses

public class ContentApiModelConverter : IContentApiModelConverter
{
    public ConvertedContentApiModel Convert(IContent content, ConverterContext converterContext)
    {
        var model = new ConvertedContentApiModel();

        model.Properties.Add("tracking", new
        {
            gaTrackingId = "G-XXXXXXXXXX",
            gtmContainerId = "GTM-XXXXXXX",
            metaPixelId = "1234567890"
        });

        return model;
    }
}

CORS Issues

Problem: API requests blocked by CORS

Solution: Configure CORS (CMS 12+)

public void ConfigureServices(IServiceCollection services)
{
    services.AddCors(options =>
    {
        options.AddPolicy("AllowFrontend", builder =>
        {
            builder.WithOrigins("https://frontend.example.com")
                   .AllowAnyHeader()
                   .AllowAnyMethod();
        });
    });
}

public void Configure(IApplicationBuilder app)
{
    app.UseCors("AllowFrontend");
}

Common Error Messages

"Cannot read property 'push' of undefined"

Cause: dataLayer not initialized before GTM

Solution: Initialize dataLayer before GTM script

<script>
  window.dataLayer = window.dataLayer || [];
</script>
<!-- GTM script here -->

"gtag is not defined"

Cause: GA4 script not loaded or blocked

Solutions:

  1. Check script is loading: Network tab → filter for gtag
  2. Verify not blocked by CSP
  3. Check ad blockers disabled (for testing)
  4. Ensure script loads before gtag() calls

"fbq is not defined"

Cause: Meta Pixel script not loaded

Solutions:

  1. Check script loading: Network tab → filter for fbevents
  2. Verify Pixel ID is correct
  3. Check CSP headers allow Facebook
  4. Test with ad blockers disabled

Debugging Tools

Browser Developer Tools

Console: Check for JavaScript errors

// Enable verbose logging
localStorage.setItem('debug', 'true');

Network: Monitor requests

  • Filter: google-analytics.com, googletagmanager.com, facebook.com
  • Check for 200 status codes
  • Inspect request payloads

Application: Check cookies and storage

  • Cookies: _ga, _gid for GA4
  • LocalStorage: dataLayer persistence

Extensions

  1. Google Tag Assistant: Verify GTM/GA4 setup
  2. Meta Pixel Helper: Check Meta Pixel events
  3. DataLayer Inspector: View GTM data layer
  4. Lighthouse: Performance auditing

Server-Side Debugging

Enable detailed logging:

// log4net.config or appsettings.json
{
  "EPiServer": {
    "Logging": {
      "Level": "Debug"
    }
  }
}

Log tracking events:

_logger.Debug($"Tracking event: {eventName}, Parameters: {JsonConvert.SerializeObject(parameters)}");

Best Practices

  1. Always Check Edit Mode: Prevent tracking in edit mode
  2. Test Across Modes: Test in view, edit, and preview modes
  3. Use Configuration: Store IDs in config, not hard-coded
  4. Implement Error Handling: Gracefully handle tracking failures
  5. Monitor Performance: Regular performance audits
  6. Version Control: Track changes to tracking implementations
  7. Document Custom Events: Maintain event documentation
  8. Test Before Deploy: Use staging environment for testing

Getting Help

Episerver Resources

Analytics Resources

Performance

Tracking

Integration