File: //proc/self/root/tmp/ezdns_app_body.txt
<!doctype html>
<html lang="de">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>DNS Check für Domains: DNSSEC, SPF & DMARC | ezdns.support</title>
<meta name="description" content="DNS-Check für Domain Owner & KMU: Delegation, DNSSEC, Mail-Sicherheit (SPF/DKIM/DMARC) und Performance – mit verständlichen Erklärungen und konkreten Fixes." />
<link rel="canonical" href="https://ezdns.support/" />
<meta name="robots" content="index, follow" />
<meta name="theme-color" content="#020617" />
<meta property="og:type" content="website" />
<meta property="og:site_name" content="ezdns.support" />
<meta property="og:title" content="DNS Check für Domains: DNSSEC, SPF & DMARC" />
<meta property="og:description" content="DNS-Check für Domain Owner & KMU: Delegation, DNSSEC, Mail-Sicherheit (SPF/DKIM/DMARC) und Performance – mit verständlichen Erklärungen und konkreten Fixes." />
<meta property="og:url" content="https://ezdns.support/" />
<meta property="og:image" content="https://ezdns.support/app/logo.svg" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:title" content="DNS Check für Domains: DNSSEC, SPF & DMARC" />
<meta name="twitter:description" content="DNS-Check für Domain Owner & KMU: Delegation, DNSSEC, Mail-Sicherheit (SPF/DKIM/DMARC) und Performance – mit verständlichen Erklärungen und konkreten Fixes." />
<meta name="twitter:image" content="https://ezdns.support/app/logo.svg" />
<link rel="icon" href="/app/logo.svg" type="image/svg+xml" />
<link rel="preconnect" href="https://rsms.me/" />
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
<link rel="stylesheet" href="/app/assets/app.css" />
<!-- Google AdSense -->
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1965425453542572" crossorigin="anonymous"></script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "ezdns.support",
"url": "https://ezdns.support/"
}
</script>
</head>
<body class="bg-slate-950 text-slate-100">
<div class="max-w-7xl mx-auto p-6">
<header class="flex items-center justify-between">
<a href="/" class="flex items-center gap-3">
<img src="/app/logo.svg" alt="ezdns.support" class="h-8 w-auto" />
</a>
</header>
<!-- Hero -->
<section class="mt-6 bg-gradient-to-br from-slate-900 to-slate-800 rounded-2xl p-6 border border-slate-800">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 items-start">
<div>
<h1 class="text-3xl font-bold">DNS‑Check für deine Domain – ohne Rätselraten</h1>
<p class="mt-3 text-slate-300">Für Domain Owner & KMU: ezdns.support prüft Delegation, DNSSEC, Mail‑Sicherheit (SPF/DKIM/DMARC) und Performance – und erklärt verständlich, was zu tun ist.</p>
<div class="mt-3 grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm text-slate-200">
<div class="flex items-center gap-2"><span class="text-emerald-300">•</span><span>Übersicht „gut / ok / kritisch“</span></div>
<div class="flex items-center gap-2"><span class="text-emerald-300">•</span><span>Erklärungen pro Metrik ("?")</span></div>
<div class="flex items-center gap-2"><span class="text-emerald-300">•</span><span>Report teilen, CSV/PDF Export, Badge</span></div>
<div class="flex items-center gap-2"><span class="text-emerald-300">•</span><span>API‑First für Automatisierung</span></div>
</div>
<div class="mt-4 flex flex-wrap gap-3">
<button id="ctaFocus" class="px-5 py-2 rounded-lg bg-green-600 text-white">Kostenlosen Scan starten</button>
<a href="/docs" class="px-5 py-2 rounded-lg border border-slate-700 text-slate-200">API Docs</a>
<a href="https://support.panomity.com/tickets/new/" target="_blank" rel="noopener" class="px-5 py-2 rounded-lg border border-slate-700 text-slate-200">Kontakt</a>
</div>
</div>
<div class="bg-slate-900/60 border border-slate-800 rounded-2xl p-4">
<div class="text-xs uppercase tracking-wide text-slate-400">Sofort‑Scan</div>
<div class="mt-2 flex flex-wrap items-center gap-2">
<input id="domain" class="flex-1 min-w-[220px] px-3 py-2 border border-slate-300 rounded-lg text-base bg-white text-slate-900 placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-blue-600" placeholder="example.com" />
<button id="scan" class="shrink-0 px-4 py-2 text-base bg-green-600 text-white rounded-lg">Scan</button>
</div>
<div class="mt-2">
<label class="flex items-center gap-2 text-slate-300 text-sm"><input id="listed" type="checkbox" class="accent-blue-600" checked /> im Verlauf anzeigen</label>
</div>
<div class="mt-4">
<div class="flex flex-wrap gap-2 text-sm">
<button class="tab-btn px-3 py-1.5 rounded-lg bg-slate-800 text-slate-100" data-tab="why">Warum</button>
<button class="tab-btn px-3 py-1.5 rounded-lg border border-slate-700 text-slate-200" data-tab="checks">Checks</button>
<button class="tab-btn px-3 py-1.5 rounded-lg border border-slate-700 text-slate-200" data-tab="pricing">Preise</button>
<button class="tab-btn px-3 py-1.5 rounded-lg border border-slate-700 text-slate-200" data-tab="scans">Letzte Scans</button>
</div>
<div class="mt-3">
<div id="tab-why" class="tab-panel text-sm text-slate-300">
<div class="grid grid-cols-1 gap-2">
<div><span class="text-slate-100 font-medium">Vermeide Ausfälle:</span> Delegation/DNSSEC-Probleme führen oft zu kompletten Nichterreichbarkeiten.</div>
<div><span class="text-slate-100 font-medium">Bessere Zustellbarkeit:</span> SPF/DMARC reduziert Spoofing und verbessert Mail-Delivery.</div>
<div><span class="text-slate-100 font-medium">Schneller handeln:</span> „gut/ok/kritisch“ + Erklärungen pro Metrik.</div>
</div>
</div>
<div id="tab-checks" class="tab-panel hidden text-sm text-slate-300">
<div class="grid grid-cols-1 gap-2">
<div><span class="text-slate-100 font-medium">Delegation:</span> Parent/Child NS, Glue, Lame NS, AXFR, Recursion</div>
<div><span class="text-slate-100 font-medium">Mail:</span> MX, SPF (Lookups), DMARC Policy, DKIM Hinweise, CAA</div>
<div><span class="text-slate-100 font-medium">DNSSEC:</span> DS/DNSKEY Match, RRSIG Expiry, Negative Signing</div>
<div><span class="text-slate-100 font-medium">Performance:</span> p50/p95 und Score</div>
</div>
</div>
<div id="tab-pricing" class="tab-panel hidden text-sm text-slate-300">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<!-- Free Plan -->
<div class="bg-slate-900 border border-slate-700 rounded-xl p-4">
<h3 class="text-lg font-bold mb-2">Free</h3>
<div class="text-3xl font-bold mb-1">€0<span class="text-sm text-slate-400">/Monat</span></div>
<p class="text-slate-400 text-sm mb-3">Für gelegentliche Checks</p>
<ul class="text-sm space-y-1 mb-4">
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>5 Scans pro Monat</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Basis Delegation Check</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Basis DNSSEC Check</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>7 Tage Historie</span>
</li>
<li class="flex items-start gap-2">
<span class="text-slate-500">✕</span>
<span class="text-slate-500">API-Zugang</span>
</li>
</ul>
<button onclick="checkout('free')" class="w-full py-2 rounded-lg bg-slate-800 text-slate-200 hover:bg-slate-700 transition">Loslegen</button>
</div>
<!-- Pro Plan -->
<div class="bg-slate-900 border-2 border-blue-500 rounded-xl p-4 relative">
<div class="absolute -top-3 left-1/2 transform -translate-x-1/2 bg-blue-600 text-white px-3 py-1 rounded-full text-xs font-semibold">Beliebt</div>
<h3 class="text-lg font-bold mb-2">Pro</h3>
<div class="text-3xl font-bold mb-1">€29<span class="text-sm text-slate-400">/Monat</span></div>
<p class="text-slate-400 text-sm mb-3">Für professionelle Nutzung</p>
<ul class="text-sm space-y-1 mb-4">
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Unbegrenzte Scans</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Vollständige Delegation Check</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Vollständiger DNSSEC Check</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Mail-Security Check (SPF/DKIM/DMARC)</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Performance-Analyse</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>CSV/PDF Export</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>1 Jahr Historie</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>API-Zugang (10k Requests)</span>
</li>
</ul>
<button onclick="checkout('pro_monthly')" class="w-full py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 transition font-semibold">Starten - €29/Monat</button>
</div>
<!-- Business Plan -->
<div class="bg-slate-900 border border-slate-700 rounded-xl p-4">
<h3 class="text-lg font-bold mb-2">Business</h3>
<div class="text-3xl font-bold mb-1">€99<span class="text-sm text-slate-400">/Monat</span></div>
<p class="text-slate-400 text-sm mb-3">Für Teams & Agenturen</p>
<ul class="text-sm space-y-1 mb-4">
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Alles aus Pro</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Bis zu 10 Domains</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>White-Label Reports</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Priority Support</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Team-Zugang (5 User)</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Webhook-Benachrichtigungen</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Erweiterte API-Limits</span>
</li>
</ul>
<button onclick="checkout('business_monthly')" class="w-full py-2 rounded-lg bg-slate-800 text-slate-200 hover:bg-slate-700 transition">Starten - €99/Monat</button>
</div>
<!-- Agency Plan -->
<div class="bg-slate-900 border border-slate-700 rounded-xl p-4">
<h3 class="text-lg font-bold mb-2">Agency</h3>
<div class="text-3xl font-bold mb-1">€199<span class="text-sm text-slate-400">/Monat</span></div>
<p class="text-slate-400 text-sm mb-3">Für Reseller & Partners</p>
<ul class="text-sm space-y-1 mb-4">
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Alles aus Business</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Unbegrenzte Domains</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Custom-Branding</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Reseller-Preise</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Dedicated Account Manager</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>24/7 Support</span>
</li>
<li class="flex items-start gap-2">
<span class="text-emerald-400">✓</span>
<span>Affiliate-Zugang</span>
</li>
</ul>
<button onclick="checkout('agency_monthly')" class="w-full py-2 rounded-lg bg-slate-800 text-slate-200 hover:bg-slate-700 transition">Starten - €199/Monat</button>
</div>
</div>
<!-- yearly discount -->
<div class="mt-6 bg-slate-900 border border-slate-800 rounded-xl p-4 text-center">
<label class="flex items-center justify-center gap-3 cursor-pointer">
<input type="checkbox" id="yearlyBilling" onchange="toggleYearly()" class="accent-blue-600" />
<span><strong>20% sparen</strong> bei jährlicher Zahlung</span>
</label>
<div class="mt-2 text-sm text-slate-400">
Monatlich: <span id="monthlyPrice">ab €29</span>
</div>
</div>
<!-- guarantee -->
<div class="mt-6 bg-slate-900 border border-slate-800 rounded-xl p-4">
<div class="flex items-center gap-4">
<div class="text-3xl">🛡️</div>
<div>
<strong class="text-lg">14-Tage Geld-zurück-Garantie</strong>
<p class="text-slate-400 text-sm">Jederzeit kündbar</p>
</div>
</div>
</div>
</div>
<div id="tab-scans" class="tab-panel hidden">
<table class="w-full text-sm">
<thead>
<tr class="text-left text-slate-400">
<th class="py-2">Domain</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody id="scans"></tbody>
</table>
<div class="mt-2 text-xs text-slate-400">Tipp: Im Report gibt es Farbcodierung und Erklärungen pro Metrik.</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
<footer class="mt-12 text-center text-sm text-slate-400">
<div class="space-x-4">
<a class="text-blue-400 hover:underline" href="/docs" target="_blank">API Docs</a>
<a class="text-blue-400 hover:underline" href="/app/imprint.html">Imprint</a>
<a class="text-blue-400 hover:underline" href="/app/privacy.html">Privacy</a>
<a class="text-blue-400 hover:underline" href="https://support.panomity.com/tickets/new/" target="_blank" rel="noopener">Contact</a>
</div>
<div class="mt-2"> © <span id="year"></span> <a class="text-blue-400 hover:underline" href="https://panomity.de/" target="_blank" rel="noopener">Panomity GmbH</a></div>
</footer>
<script>
const apiBase = '';
const scansTbody = document.getElementById('scans');
const scanBtn = document.getElementById('scan');
const domainInput = document.getElementById('domain');
const API_KEY = 'dev-key';
async function fetchJSON(url, opts={}) {
const headers = Object.assign({ 'x-api-key': API_KEY }, opts.headers||{});
const res = await fetch(url, Object.assign({}, opts, { headers }));
if (!res.ok) throw new Error('HTTP '+res.status);
return await res.json();
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function toast(message, variant = 'info', opts = {}) {
const hostId = 'toastHost';
let host = document.getElementById(hostId);
if (!host) {
host = document.createElement('div');
host.id = hostId;
host.className = 'fixed top-4 right-4 z-50 flex flex-col gap-2';
document.body.appendChild(host);
}
const t = document.createElement('div');
const cls = variant === 'success'
? 'bg-emerald-900 text-emerald-100 border border-emerald-700'
: variant === 'error'
? 'bg-red-900 text-red-100 border border-red-700'
: 'bg-slate-900 text-slate-100 border border-slate-700';
t.className = `px-3 py-2 rounded shadow max-w-sm ${cls}`;
const row = document.createElement('div');
row.className = 'flex items-center gap-3';
const msg = document.createElement('div');
msg.className = 'text-sm';
msg.textContent = message;
row.appendChild(msg);
if (opts.actionHref && opts.actionLabel) {
const a = document.createElement('a');
a.href = opts.actionHref;
a.className = 'text-sm text-blue-200 hover:underline whitespace-nowrap';
a.textContent = opts.actionLabel;
row.appendChild(a);
}
t.appendChild(row);
host.appendChild(t);
const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : 3500;
if (timeoutMs > 0) {
setTimeout(() => {
t.remove();
if (host && host.childElementCount === 0) host.remove();
}, timeoutMs);
}
return t;
}
const scanPollers = new Map();
async function pollScanUntilDone(scanId, { maxMs = 120000, intervalMs = 2000 } = {}) {
const start = Date.now();
while (Date.now() - start < maxMs) {
await sleep(intervalMs);
const scan = await fetchJSON(`${apiBase}/v1/scan/${scanId}`);
if (scan && scan.status === 'done') return scan;
}
throw new Error('timeout');
}
function row(status) {
const cls = status === 'done' ? 'bg-emerald-900 text-emerald-200' : 'bg-amber-900 text-amber-200';
return `<span class="px-2 py-0.5 rounded ${cls}">${status}</span>`;
}
function setActiveTab(tab) {
const buttons = document.querySelectorAll('.tab-btn');
const panels = document.querySelectorAll('.tab-panel');
for (const b of buttons) {
const isActive = b.dataset.tab === tab;
b.className = isActive
? 'tab-btn px-3 py-1.5 rounded-lg bg-slate-800 text-slate-100'
: 'tab-btn px-3 py-1.5 rounded-lg border border-slate-700 text-slate-200';
}
for (const p of panels) {
p.classList.toggle('hidden', p.id !== `tab-${tab}`);
}
}
async function loadScans() {
const data = await fetchJSON(`${apiBase}/v1/scans?limit=5`);
scansTbody.innerHTML = '';
for (const s of data.items) {
const tr = document.createElement('tr');
const domain = s.domain || s.domain_id;
tr.innerHTML = `
<td class="py-2 text-blue-300">${domain}</td>
<td>${row(s.status)}</td>
<td><a href="/app/detail.html?id=${s.id}" class="text-sm text-blue-400 hover:underline">Open</a></td>
`;
scansTbody.appendChild(tr);
}
}
// kein separates Detail-Panel mehr
const listedCheckbox = document.getElementById('listed');
scanBtn.addEventListener('click', async () => {
const d = domainInput.value.trim();
if (!d) return;
try {
scanBtn.disabled = true; scanBtn.textContent = 'Starting…';
const created = await fetchJSON(`${apiBase}/v1/scan`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ domain: d, listed: !!listedCheckbox.checked }) });
const scanId = created && created.id;
toast('Scan läuft… wir sagen Bescheid, sobald er fertig ist.', 'info', { timeoutMs: 4000 });
setActiveTab('scans');
await loadScans();
if (scanId && !scanPollers.has(scanId)) {
const p = pollScanUntilDone(scanId)
.then(async () => {
toast('Scan fertig.', 'success', { actionLabel: 'Report öffnen', actionHref: `/app/detail.html?id=${scanId}`, timeoutMs: 9000 });
await loadScans();
})
.catch(() => {
toast('Scan läuft noch – bitte in „Letzte Scans“ prüfen.', 'info', { timeoutMs: 6000 });
})
.finally(() => {
scanPollers.delete(scanId);
});
scanPollers.set(scanId, p);
}
} catch (e) {
toast('Scan konnte nicht gestartet werden.', 'error', { timeoutMs: 5000 });
} finally {
scanBtn.disabled = false; scanBtn.textContent = 'Scan';
}
});
// Pricing Configuration
const pricing = {
monthly: {
pro: { price: 29, name: 'Pro Monthly' },
business: { price: 99, name: 'Business Monthly' },
agency: { price: 199, name: 'Agency Monthly' }
},
yearly: {
pro: { price: 279, name: 'Pro Yearly' },
business: { price: 999, name: 'Business Yearly' },
agency: { price: 1999, name: 'Agency Yearly' }
}
};
// Stripe Checkout Links (konfigurierbar)
const stripeCheckoutLinks = {
pro_monthly: 'https://buy.stripe.com/EXAMPLE_PRO_MONTHLY_LINK',
pro_yearly: 'https://buy.stripe.com/EXAMPLE_PRO_YEARLY_LINK',
business_monthly: 'https://buy.stripe.com/EXAMPLE_BUSINESS_MONTHLY_LINK',
business_yearly: 'https://buy.stripe.com/EXAMPLE_BUSINESS_YEARLY_LINK',
agency_monthly: 'https://buy.stripe.com/EXAMPLE_AGENCY_MONTHLY_LINK',
agency_yearly: 'https://buy.stripe.com/EXAMPLE_AGENCY_YEARLY_LINK'
};
// Checkout Funktion
function checkout(plan) {
const isYearly = document.getElementById('yearlyBilling') && document.getElementById('yearlyBilling').checked;
const actualPlan = isYearly ? plan.replace('monthly', 'yearly') : plan;
const checkoutUrl = stripeCheckoutLinks[actualPlan];
if (checkoutUrl && !checkoutUrl.includes('EXAMPLE')) {
// Track event
if (typeof _paq !== 'undefined') {
_paq.push(['trackEvent', 'upgrade_clicked', { plan: actualPlan }]);
}
// Redirect to Stripe Checkout
toast('Du wirst zu Stripe Checkout weitergeleitet...', 'info', { timeoutMs: 2000 });
setTimeout(() => {
window.location.href = checkoutUrl;
}, 1000);
} else {
toast('⚠️ Stripe Checkout Links müssen noch konfiguriert werden!\n\nBitte kontaktiere den Support, um die Stripe Checkout Links zu konfigurieren.', 'error', { timeoutMs: 8000 });
}
}
// Jährlich/Monatlich Umschalten
function toggleYearly() {
const isYearly = document.getElementById('yearlyBilling') && document.getElementById('yearlyBilling').checked;
const monthlyPriceEl = document.getElementById('monthlyPrice');
if (isYearly) {
// 20% Rabatt: 29 * 0.8 = 23.2 ≈ €23
// 99 * 0.8 = 79.2 ≈ €79
// 199 * 0.8 = 159.2 ≈ €159
const monthlyPrices = { pro: 23, business: 79, agency: 159 };
// Aktualisiere alle Preis-Elemente
const priceEls = document.querySelectorAll('[data-plan]');
priceEls.forEach(el => {
const plan = el.dataset.plan;
if (monthlyPrices[plan]) {
el.textContent = '€' + monthlyPrices[plan];
}
});
if (monthlyPriceEl) {
monthlyPriceEl.textContent = '€' + monthlyPrices.pro;
}
toast('Jahresrabatt aktiv: Du sparst 20%', 'success', { timeoutMs: 2000 });
} else {
// Normale Preise
const monthlyPrices = { pro: 29, business: 99, agency: 199 };
// Aktualisiere alle Preis-Elemente
const priceEls = document.querySelectorAll('[data-plan]');
priceEls.forEach(el => {
const plan = el.dataset.plan;
if (monthlyPrices[plan]) {
el.textContent = '€' + monthlyPrices[plan];
}
});
if (monthlyPriceEl) {
monthlyPriceEl.textContent = '€' + monthlyPrices.pro;
}
}
}
// Tabs + initial state
document.querySelectorAll('.tab-btn').forEach((b) => {
b.addEventListener('click', () => setActiveTab(b.dataset.tab));
});
setActiveTab('why');
const cta = document.getElementById('ctaFocus');
if (cta) {
cta.addEventListener('click', () => {
domainInput.focus();
setActiveTab('scans');
});
}
loadScans();
// Footer year
document.getElementById('year').textContent = new Date().getFullYear();
// Matomo config + tracking
(async () => {
try {
await import('/config.js');
const cfg = window.__APP_CONFIG__ || {};
if (cfg.MATOMO_URL && cfg.MATOMO_SITE_ID) {
var _paq = (window._paq = window._paq || []);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u = cfg.MATOMO_URL.endsWith('/') ? cfg.MATOMO_URL : cfg.MATOMO_URL + '/';
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', cfg.MATOMO_SITE_ID]);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
})();
}
} catch (e) { /* ignore */ }
})();
</script>
</body>
</html>