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) onhttp://localhost:4400cmp-registry.<region>.<yourdomain>→ reverse-proxy to the Registry (NestJS) onhttp://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.andza.) or separate servers if latency or data residency require it.
2) Prepare IIS
- Install URL Rewrite and Application Request Routing (ARR) via Web Platform Installer or Microsoft download pages.
- For each IIS site (Portal & Registry):
- App Pool: No Managed Code, 32-bit disabled, Start Mode = AlwaysRunning
- Bindings:
httpswith 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/4500internally, 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.configabove)
7) Smoke test checklist
- Banner appears on first visit (private window)
- Portal → Analytics → Diagnostics shows region decision + Consent Mode ✅ after Accept
- GA4 waits for consent (use DebugView); no analytics cookies on Reject
- Portal → Artifacts → Consents/Receipts exports CSV/JSON successfully
8) Troubleshooting
| Symptom | Observation | Fix |
|---|---|---|
| Banner missing | No banner rendered | Ensure snippet in <head> with correct Site Key and clear caches |
| Tags fire on Reject | GA/Ads still run | Use GA4 Consent Mode template; load tags only when allowAnalytics |
| Diagnostics show "GDPR fallback" | Region uncertain | Forward GeoIP/X-Forwarded-* headers; fallback defaults to strict |
| Region latency > 500 ms | Slow diagnostics | Check ingress/CDN and GeoIP database freshness |
9) Rollback & maintenance
- Comment out the snippet to disable gating instantly
- Use IIS
app_offline.htmduring 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.