Template
Populate the client website template with catalog feature flags.
Extract always-on public/portal/UTM plus optional email_sms, directmail, blog, payments, social, and social_ai so new client sites can be bootstrapped from this seed. Refs #1 Refs #2 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
{% extends "portal_base.html" %}
|
||||
{% block title %}Analytics · Portal{% endblock %}
|
||||
{% block topbar_title %}Analytics{% endblock %}
|
||||
{% block portal_content %}
|
||||
<div class="analytics-overview">
|
||||
<div class="stat-card">
|
||||
<div class="label">Views (last 30 days)</div>
|
||||
<div class="value">{{ pageviews_last_30_days }}</div>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<div class="panel-h"><h2>Top pages</h2><span class="muted" style="font-size:12px">Public visits, last 30 days</span></div>
|
||||
<div class="panel-b" style="padding:0">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Page</th>
|
||||
<th>Visits</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in top_pages %}
|
||||
<tr>
|
||||
<td>{{ row.path }}</td>
|
||||
<td>{{ row.count }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="2" class="empty-state">No public page views in the last 30 days.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-row">
|
||||
<div class="stat-card">
|
||||
<div class="label">UTM landings</div>
|
||||
<div class="value">{{ total_visits }}</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="label">Attributed leads</div>
|
||||
<div class="value">{{ total_attributed }}</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="label">Top source</div>
|
||||
<div class="value" style="font-size:18px">{{ top_source|default:"—" }}</div>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<div class="label">Top campaign</div>
|
||||
<div class="value" style="font-size:18px">{{ top_campaign|default:"—" }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-h"><h2>Landing volume by source</h2></div>
|
||||
<div class="panel-b">
|
||||
<div class="chart-placeholder">
|
||||
{% for row in visits_by_source|slice:":8" %}
|
||||
<div class="bar" style="height:{{ row.bar_pct }}%" title="{{ row.utm_source|default:'(direct)' }}: {{ row.count }}"></div>
|
||||
{% empty %}
|
||||
<div class="bar" style="height:12%"></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-h"><h2>UTM landings</h2><span class="muted" style="font-size:12px">From ?utm_* hits</span></div>
|
||||
<div class="panel-b" style="padding:0">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>Medium</th>
|
||||
<th>Campaign</th>
|
||||
<th>Landings</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in visits_by_combo %}
|
||||
<tr>
|
||||
<td>{{ row.utm_source|default:"(direct)" }}</td>
|
||||
<td>{{ row.utm_medium|default:"—" }}</td>
|
||||
<td>{{ row.utm_campaign|default:"—" }}</td>
|
||||
<td>{{ row.count }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="4" class="empty-state">No UTM landings yet. Open a public URL with ?utm_source=…</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-h"><h2>Recent landings</h2></div>
|
||||
<div class="panel-b" style="padding:0">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>When</th>
|
||||
<th>Path</th>
|
||||
<th>Source</th>
|
||||
<th>Campaign</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for visit in recent_visits %}
|
||||
<tr>
|
||||
<td>{{ visit.created_at|date:"M j, g:i A" }}</td>
|
||||
<td>{{ visit.path }}</td>
|
||||
<td>{{ visit.utm_source|default:"—" }}</td>
|
||||
<td>{{ visit.utm_campaign|default:"—" }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="4" class="empty-state">No visits recorded.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
<div class="panel-h"><h2>Lead attribution</h2><span class="muted" style="font-size:12px">After contact-form submit</span></div>
|
||||
<div class="panel-b" style="padding:0">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Source</th>
|
||||
<th>Medium</th>
|
||||
<th>Campaign</th>
|
||||
<th>Leads</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in leads_by_combo %}
|
||||
<tr>
|
||||
<td>{{ row.utm_source|default:"(direct)" }}</td>
|
||||
<td>{{ row.utm_medium|default:"—" }}</td>
|
||||
<td>{{ row.utm_campaign|default:"—" }}</td>
|
||||
<td>{{ row.count }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr><td colspan="4" class="empty-state">No attributed leads yet — submit the contact form after a UTM landing.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user