feat(analytics): admin field for Google Analytics (GA4) ID
Adds a "Measurement ID" input under admin → Site Identity. The value is stored as identity/ga_id (existing bulk-settings endpoint, no API change). When set, _Layout injects the GA4 gtag.js snippet into <head> on every page (home, blog, gallery, posts). Empty value = disabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -6,12 +6,24 @@
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
var _logoUrl = _identity.FirstOrDefault(s => s.Key == "logo")?.Value ?? "";
|
var _logoUrl = _identity.FirstOrDefault(s => s.Key == "logo")?.Value ?? "";
|
||||||
var _faviconUrl = _identity.FirstOrDefault(s => s.Key == "favicon")?.Value ?? "";
|
var _faviconUrl = _identity.FirstOrDefault(s => s.Key == "favicon")?.Value ?? "";
|
||||||
|
var _gaId = (_identity.FirstOrDefault(s => s.Key == "ga_id")?.Value ?? "").Trim();
|
||||||
}
|
}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="fa" dir="rtl">
|
<html lang="fa" dir="rtl">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
@if (!string.IsNullOrEmpty(_gaId))
|
||||||
|
{
|
||||||
|
<!-- Google Analytics (GA4) -->
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=@_gaId"></script>
|
||||||
|
<script>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag(){dataLayer.push(arguments);}
|
||||||
|
gtag('js', new Date());
|
||||||
|
gtag('config', '@Html.Raw(_gaId)');
|
||||||
|
</script>
|
||||||
|
}
|
||||||
@RenderSection("Head", required: false)
|
@RenderSection("Head", required: false)
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
|||||||
@@ -630,6 +630,26 @@ tr:hover td{background:#FAFBFC}
|
|||||||
<p style="font-size:.78rem;color:var(--light);margin-top:1rem">⚠️ پس از ذخیره، تغییرات فاویکون ممکن است نیاز به پاککردن کش مرورگر داشته باشد.</p>
|
<p style="font-size:.78rem;color:var(--light);margin-top:1rem">⚠️ پس از ذخیره، تغییرات فاویکون ممکن است نیاز به پاککردن کش مرورگر داشته باشد.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Google Analytics -->
|
||||||
|
<div class="card" style="margin-top:1.2rem">
|
||||||
|
<div class="card-header"><div class="card-title">📊 گوگل آنالیتیکس (Google Analytics)</div></div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p style="font-size:.83rem;color:var(--mid);margin-bottom:1.2rem;line-height:1.8">
|
||||||
|
شناسه اندازهگیری گوگل آنالیتیکس ۴ (GA4) را وارد کنید تا کد رهگیری بهصورت خودکار در تمام صفحات سایت قرار گیرد.<br>
|
||||||
|
<strong>فرمت:</strong> با <code>G-</code> شروع میشود — مثال: <code dir="ltr">G-XXXXXXXXXX</code><br>
|
||||||
|
<span style="color:var(--light)">برای دریافت شناسه: analytics.google.com ← Admin ← Data Streams ← Measurement ID</span>
|
||||||
|
</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Measurement ID</label>
|
||||||
|
<input id="si-ga" dir="ltr" placeholder="G-XXXXXXXXXX" />
|
||||||
|
</div>
|
||||||
|
<div style="margin-top:1rem">
|
||||||
|
<button class="btn btn-primary" onclick="saveSiteIdentity()">ذخیره شناسه آنالیتیکس</button>
|
||||||
|
</div>
|
||||||
|
<p style="font-size:.78rem;color:var(--light);margin-top:1rem">برای غیرفعالکردن، این فیلد را خالی کنید و ذخیره بزنید.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="page" id="page-security">
|
<div class="page" id="page-security">
|
||||||
@@ -1464,6 +1484,7 @@ async function loadSiteIdentity() {
|
|||||||
// Set hidden inputs
|
// Set hidden inputs
|
||||||
document.getElementById('si-logo').value = vals.logo || '';
|
document.getElementById('si-logo').value = vals.logo || '';
|
||||||
document.getElementById('si-favicon').value = vals.favicon || '';
|
document.getElementById('si-favicon').value = vals.favicon || '';
|
||||||
|
document.getElementById('si-ga').value = vals.ga_id || '';
|
||||||
// Show previews
|
// Show previews
|
||||||
showPreview('prev-si-logo', vals.logo || '');
|
showPreview('prev-si-logo', vals.logo || '');
|
||||||
showPreview('prev-si-favicon', vals.favicon || '');
|
showPreview('prev-si-favicon', vals.favicon || '');
|
||||||
@@ -1486,9 +1507,10 @@ function updateSiteIdentityPreview(logoUrl, faviconUrl) {
|
|||||||
async function saveSiteIdentity() {
|
async function saveSiteIdentity() {
|
||||||
const logo = document.getElementById('si-logo').value;
|
const logo = document.getElementById('si-logo').value;
|
||||||
const favicon = document.getElementById('si-favicon').value;
|
const favicon = document.getElementById('si-favicon').value;
|
||||||
|
const ga_id = (document.getElementById('si-ga').value || '').trim();
|
||||||
await api('/api/settings/identity', {
|
await api('/api/settings/identity', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify({ settings: { logo, favicon } })
|
body: JSON.stringify({ settings: { logo, favicon, ga_id } })
|
||||||
});
|
});
|
||||||
updateSiteIdentityPreview(logo, favicon);
|
updateSiteIdentityPreview(logo, favicon);
|
||||||
toast('ذخیره شد ✓ — برای اعمال فاویکون کش مرورگر را پاک کنید');
|
toast('ذخیره شد ✓ — برای اعمال فاویکون کش مرورگر را پاک کنید');
|
||||||
|
|||||||
Reference in New Issue
Block a user