{% extends 'base.html' %} {% block title %}Market & Customer Insights — Admin{% endblock %} {% block content %}
Admin Portal

Market & Customer Insights

← Back to portal

Window: last {{ days }} days · 90 days · 180 days · 365 days · All time

Overview

Total orders {{ data.overview.total_orders }} {{ data.overview.unique_customers }} unique customers
Delivered {{ data.overview.delivered_count }}
Revenue (delivered) TSh {{ data.overview.total_revenue|floatformat:0 }}
Avg order value TSh {{ data.overview.avg_order_value|floatformat:0 }}

Top products (by revenue)

{% for p in data.top_products %} {% empty %} {% endfor %}
ProductQty soldOrdersRevenue% of revenueStock left
{{ p.name }} {{ p.quantity }} {{ p.order_count }} TSh {{ p.revenue|floatformat:0 }} {{ p.pct_of_revenue }}% {% if p.stock_qty is not None %}{{ p.stock_qty }}{% if p.stock_qty < 10 %} low{% endif %}{% else %}—{% endif %}
No completed orders in this window yet.

Orders & spend by area

Matched to the nearest known area for each delivery pin — the closest proxy this app has for demand/population by neighborhood.{% if data.unmatched_area_count %} {{ data.unmatched_area_count }} order{{ data.unmatched_area_count|pluralize }} had no delivery pin to match.{% endif %}

{% for a in data.spend_by_area %} {% empty %} {% endfor %}
AreaOrdersRevenue
{{ a.area }}{{ a.order_count }}TSh {{ a.revenue|floatformat:0 }}
No geolocated orders yet.

Orders by source market

Derived from the assigned picker's registered market — a proxy, not a direct order field.

{% for m in data.orders_by_market %} {% empty %} {% endfor %}
MarketOrdersRevenue
{{ m.market }}{{ m.order_count }}TSh {{ m.revenue|floatformat:0 }}
No orders yet.

Which days customers order

{% for d in data.day_pattern %}
{% if d.count > 0 %}{{ d.count }}{% endif %}
{{ d.label }}
{% endfor %}

What time of day (East Africa Time)

{% for h in data.hour_pattern %}
{% if h.count > 0 %}{{ h.count }}{% endif %}
{{ h.label }}
{% endfor %}

Monthly / seasonal trend

{% for m in data.monthly_trend %}
{% if m.order_count > 0 %}{{ m.order_count }}{% endif %}
{{ m.label }}
{% endfor %}

New vs. returning customers (per month)

{% for c in data.customer_trend %} {% endfor %}
MonthNew customersReturning customers
{{ c.label }}{{ c.new_customers }}{{ c.returning_customers }}

Delivery cost analysis

{% if data.delivery_cost %}
Avg delivery fee TSh {{ data.delivery_cost.avg_delivery_fee|floatformat:0 }}
Avg distance {{ data.delivery_cost.avg_distance_km|floatformat:1 }} km
Realized fee / km TSh {{ data.delivery_cost.fee_per_km|floatformat:0 }}
Avg picking fee TSh {{ data.delivery_cost.avg_picking_fee|floatformat:0 }}
Avg package fee TSh {{ data.delivery_cost.avg_package_fee|floatformat:0 }}
Quick delivery share {{ data.delivery_cost.quick_delivery_pct }}%
{% else %}

No delivered orders in this window yet.

{% endif %}

Picker ratings ({{ data.rating_breakdown.total_ratings }} total)

{% for r in data.rating_breakdown.distribution reversed %}
{{ r.stars }}★
{{ r.count }} ({{ r.pct }}%)
{% endfor %}

Pickers needing improvement

{% for p in data.rating_breakdown.needs_improvement %} {% empty %} {% endfor %}
PickerAvg ratingRatings
{{ p.name }}★ {{ p.average }}{{ p.count }}
Not enough rating data yet.

Product demand signals — what to add / restock

Most-searched terms that returned zero results

{% for s in data.demand_signals.top_zero_result_searches %} {% empty %} {% endfor %}
Search termTimes searched
{{ s.query }}{{ s.count }}
No zero-result searches logged yet.

Most-searched terms overall

{% for s in data.demand_signals.top_searches %} {% empty %} {% endfor %}
Search termTimes searched
{{ s.query }}{{ s.count }}
No searches logged yet.

Recent "Contact Us" messages

{% for m in data.demand_signals.recent_contact_messages %} {% empty %} {% endfor %}
FromMessageWhen
{{ m.name }}
{{ m.email }}
{{ m.message }} {{ m.created_at|slice:":10" }}
No contact messages yet.
{% endblock %}