{% extends "base.html" %} {% block title %}Reports{% endblock %} {% macro pct(r) %}{{ '-' if r is none else '%d%%' % (r * 100) | round }}{% endmacro %} {% macro d(cur, prev) %}{% set t = delta(cur, prev) %}{{ t }}{% endmacro %} {% macro bar(n, max) %}
{% endmacro %} {# A count that links to the rows behind it (zero stays plain text). #} {% macro n(count, key) %}{% if count and key %}{{ count }}{% else %}{{ count }}{% endif %}{% endmacro %} {% macro money(value, key) %}{% if value and key %}{{ '{:,}'.format(value) }}{% else %}{{ '{:,}'.format(value) }}{% endif %}{% endmacro %} {% block content %} {% set p = report.period %}{% set a = report.activity %}{% set f = report.funnel %} {% set o = report.outcomes %}{% set msg = report.messages %}{% set hy = report.hygiene %}

Reports

{% for name in periods if name != 'custom' %}{{ name }}{% endfor %}

{% if error %}

{{ error }}

{% endif %}

{{ fmt_date(p.start) }} to {{ fmt_date(p.end) }} ({{ p.days }}d); deltas against {{ fmt_date(report.previous.start) }} to {{ fmt_date(report.previous.end) }}. Click a number for the rows behind it.

Activity

{% for key, label in [('interactions', 'interactions'), ('companies_touched', 'companies touched'), ('new_companies', 'new companies'), ('new_contacts', 'new contacts')] %} {% endfor %}
metricperiodprevious
{{ label }}{{ n(a.totals[key], a.row_keys[key]) }} {{ d(a.totals[key], a.previous[key]) }}{{ n(a.previous[key], a.previous_row_keys[key]) }}
{% for col in a.columns %}{% endfor %} {% for r in a.weeks %} {% for col in a.columns %}{% endfor %} {% endfor %}
week{{ col }}total
{{ r.week }}{{ n(r[col], r.row_keys[col]) }}{{ n(r.total, r.row_keys.total) }}{{ bar(r.total, a.max_week) }}

Funnel

{% for r in f.entered %}{% endfor %}
stageenteredprevious
{{ r.stage }}{{ n(r.count, r.key) }} {{ d(r.count, r.previous) }}{{ n(r.previous, r.previous_key) }}
{% for r in f.conversion %}{% endfor %}
conversionreached fromreached torate
{{ r.from }} → {{ r.to }}{{ n(r.base, r.base_key) }}{{ n(r.reached, r.reached_key) }}{{ pct(r.rate) }}{{ bar(r.rate or 0, 1) }}

Of the companies that reached a stage (or later) by the period end, the share that also reached the next one.

{% for r in f.median_days %}{% endfor %}
stagecompaniesmedian days
{{ r.stage }}{{ n(r.companies, r.key) }}{{ '%g' % r.median }}
{% for r in f.pipeline %}{% endfor %}
pipeline nowcompaniesEUR/month
{{ r.stage }}{{ n(r.count, r.key) }}{{ money(r.value, r.key) }}{{ bar(r.count, f.max_pipeline) }}

Outcomes

{% for r in o.rows %}{% endfor %}
stagecountEUR/monthprevious
{{ r.stage }}{{ n(r.count, r.key) }} {{ d(r.count, r.previous) }}{{ money(r.value, r.key) }}{{ n(r.previous, r.previous_key) }}

Win rate {{ pct(o.win_rate) }} (previous {{ pct(o.previous_win_rate) }}): won / (won + lost).

{% for r in o.lost_reasons %}{% else %}{% endfor %}
lost reasoncount
{{ r.reason }}{{ n(r.count, r.key) }}
none

Messages

Sent {{ n(msg.total.sent, msg.total.sent_key) }} {{ d(msg.total.sent, msg.previous_sent) }} (previous {{ n(msg.previous_sent, msg.previous_sent_key) }}){% for s in msg.statuses %} · {{ s }} {{ n(msg.total.counts[s], msg.total.status_keys[s]) }}{% endfor %} · {{ msg.outcomes[0] }} rate {{ pct(msg.total.rate) }} (no reply after {{ msg.window }}d counts as {{ msg.outcomes[-1] }})

{% if msg.total.other %}

{{ n(msg.total.other, msg.total.status_keys.other) }} message{{ '' if msg.total.other == 1 else 's' }} with an outcome outside the configured list ({{ msg.total.other_statuses | join(', ') }}) count in sent only.

{% endif %}
{% for title, rows in [('language', msg.by_language), ('channel', msg.by_channel)] %}
{% for s in msg.statuses %}{% endfor %} {% for r in rows %}{% for s in msg.statuses %}{% endfor %}{% else %}{% endfor %}
{{ title }}sent{{ s }}rate
{{ r.key }}{{ n(r.sent, r.sent_key) }}{{ n(r.counts[s], r.status_keys[s]) }}{{ pct(r.rate) }}
none
{% endfor %}
{% for r in msg.reused %}{% else %}{% endfor %}
reused textusesrate
{{ r.preview }}{{ n(r.uses, r.sent_key) }}{{ pct(r.rate) }}
no text used twice

Sources

{% for r in report.sources.rows %}{% else %}{% endfor %}
sourcecreatedwon
{{ r.source }}{{ n(r.created, r.created_key) }}{{ n(r.won, r.won_key) }}{{ bar(r.created, report.sources.max_created) }}
none

Hygiene

{% for r in hy.overdue %}{% else %}{% endfor %}
overdue next steps ({{ n(hy.overdue | length, hy.row_keys.overdue) }})duenext step
{{ r.name }}{{ fmt_date(r.due) }}{{ r.next_step }}
none
{% for r in hy.silent %}{% else %}{% endfor %}
silent {{ hy.silent_days }}+ days ({{ n(hy.silent | length, hy.row_keys.silent) }})stagedays
{{ r.name }}{{ r.stage }}{{ r.days }}
none
{% for r in hy.no_email %}{% else %}{% endfor %}
contacts without email ({{ n(hy.no_email | length, hy.row_keys.no_email) }})company
{{ r.name }}{{ r.company }}
none
{% endblock %}