Skip to main content

Overview

This guide explains how to run the DigiWedge CMP Portal and Registry behind IIS on Windows and integrate the CMP snippet and consent gating inside an ASP.NET Core application.

Audience: Windows/IIS admins and .NET engineers. Time: 45–90 minutes.


1) Topology

  • Two IIS sites (HTTPS):
    • cmp-portal.<region>.<yourdomain> → reverse-proxy to the Portal (Node) on http://localhost:4400
    • cmp-registry.<region>.<yourdomain> → reverse-proxy to the Registry (NestJS) on http://localhost:4500
  • Your public app (e.g., www.<yourdomain>) embeds the CMP snippet and gates non-essential cookies.

Tip: Use subdomains per region (for example uk. and za.) or separate servers if latency or data residency require it.


2) Prepare IIS

  1. Install URL Rewrite and Application Request Routing (ARR) via Web Platform Installer or Microsoft download pages.
  2. For each IIS site (Portal & Registry):
    • App Pool: No Managed Code, 32-bit disabled, Start Mode = AlwaysRunning
    • Bindings: https with a valid certificate

Reverse-proxy rule (web.config)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ProxyAll" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:4400/{R:1}" />
<serverVariables>
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
<set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
</serverVariables>
</rule>
</rules>
</rewrite>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000; includeSubDomains; preload" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>

For the Registry site, change the proxy URL to http://localhost:4500/{R:1}.


3) Run the services on Windows

  • Run Portal (PORTAL_PORT=4400) and Registry (REGISTRY_PORT=4500) as Windows Services (NSSM) or via PM2 with auto-start.
  • Environment variables: region base URLs, OIDC client credentials for Portal, and DB/Redis details for the Registry.

Prefer containers? Host Docker on the server, publish 4400/4500 internally, and keep IIS as the HTTPS edge.


4) Add the CMP snippet to ASP.NET Core

Insert in _Layout.cshtml before </head> and above analytics/ads scripts:

<script
src="https://cmp-registry.<region>.<yourdomain>/v1/snippet.js"
data-site-key="YOUR_SITE_KEY"
defer
></script>

Replace <region> and <yourdomain> and copy the Site Key from Portal → Sites.


5) Gate non-essential cookies

Middleware to defer analytics cookies until consent is granted:

// Program.cs (before endpoint routing)
app.Use(async (context, next) =>
{
var consentJson = context.Request.Cookies["cmp.consent"];
var consent = string.IsNullOrEmpty(consentJson)
? new { analytics = false, marketing = false, functional = true }
: System.Text.Json.JsonSerializer.Deserialize<dynamic>(consentJson);

bool allowAnalytics = (bool?)consent?.analytics == true;
context.Items["allowAnalytics"] = allowAnalytics;

context.Response.OnStarting(() =>
{
if (!allowAnalytics)
{
var setCookies = context.Response.Headers["Set-Cookie"];
if (setCookies.Count > 0)
{
var filtered = setCookies.Where(v =>
!v.Contains("GA", StringComparison.OrdinalIgnoreCase) &&
!v.Contains("gid", StringComparison.OrdinalIgnoreCase));
context.Response.Headers["Set-Cookie"] = new Microsoft.Extensions.Primitives.StringValues(filtered.ToArray());
}
}
return Task.CompletedTask;
});

await next();
});

Razor view snippet:

@{
var allowAnalytics = (bool?)Context.Items["allowAnalytics"] == true;
}
@if (allowAnalytics)
{
<!-- GA4 / Ads scripts here -->
}

6) Security headers & CSP

  • CMP cookies: Secure; SameSite=None; Path=/
  • Add CMP hosts to script-src
  • Keep HSTS enabled (see web.config above)

7) Smoke test checklist

  1. Banner appears on first visit (private window)
  2. Portal → Analytics → Diagnostics shows region decision + Consent Mode ✅ after Accept
  3. GA4 waits for consent (use DebugView); no analytics cookies on Reject
  4. Portal → Artifacts → Consents/Receipts exports CSV/JSON successfully

8) Troubleshooting

SymptomObservationFix
Banner missingNo banner renderedEnsure snippet in <head> with correct Site Key and clear caches
Tags fire on RejectGA/Ads still runUse GA4 Consent Mode template; load tags only when allowAnalytics
Diagnostics show "GDPR fallback"Region uncertainForward GeoIP/X-Forwarded-* headers; fallback defaults to strict
Region latency > 500 msSlow diagnosticsCheck ingress/CDN and GeoIP database freshness

9) Rollback & maintenance

  • Comment out the snippet to disable gating instantly
  • Use IIS app_offline.htm during maintenance windows
  • Keep Portal/Registry updated; new configs ship with fresh ETags for safe client caching

10) Optional automation

  • PowerShell scripts to install URL Rewrite/ARR and drop web.config
  • CI deploy step (Web Deploy or Octopus) to push updated configs

Done. Michael can deploy the IIS proxy, run the services, add the snippet, and gate cookies within one sprint.