Leveraging table data
Sales Profile Tab: Setup Guide with Salesforce
This profile tab displays a rep's sales performance — win rates, closed ARR, and quota attainment — pulled live from an opportunity table.
Prerequisites
Opportunity Table
You need a table named opportunity in your ChartHop account with the following fields:
Field | Type | Description |
|---|---|---|
owner | Person | The rep who owns the opportunity |
name | Text | Opportunity/company name |
stage | Text | Deal stage (e.g. "Closed Won", "Closed Lost") |
arr | Currency/Number | Annual Recurring Revenue |
closeDate | Date | Expected or actual close date |
contractStartDate | Date | Optional. When the contract starts; used as the primary close date for attainment calculations, falls back to closeDate |
Closed Stage Convention
The template uses stage:closed to find all closed deals regardless of outcome (won or lost). Make sure your closed stages are tagged or named consistently so this filter works. Deals with stage="Closed Won" are counted separately for win rate.
Quota Field on the Person
Each rep must have a quota field on their person record. This is used for attainment calculations. The template uses asOf() to look up what their quota was in a past quarter.
What It Shows
- This Quarter — Win rate, closed won logo count and ARR, and quota attainment for the current fiscal quarter.
- Last Quarter — Same metrics for the previous fiscal quarter, using asOf() to retrieve the rep's quota at that time.
- All Time by Quarter — A summary table of logos won, ARR, quota, and attainment % for every quarter with at least one closed won deal.
- All Time Logos Won — A full list of every closed won deal, sorted by ARR descending.
How to Add the Tab
- In ChartHop, go to Profile settings and create a new custom tab.
- Set the tab to use a Rich Text / Template field type.
- Paste the template code into the editor.
- Customize as needed (see below).
Customization
Deal links
All opportunity names link to a shared Google Sheet. To update the destination, replace the URL directly in the template:
<a href="YOUR_GOOGLE_SHEET_URL">{{opp.name}}</a>
Extend the quarter date list
The all-time quarterly breakdown uses a hardcoded array of quarter start dates. Add future quarters by appending to quarterDates:
{% assign quarterDates = ['2019-07-01', ..., '2027-04-01'] %}
Each date should be the first day of a fiscal quarter.
Change the closed stage filter
If your closed stages use different naming, update the stage:closed filter. To use explicit stage names instead:
table.opportunity.find{owner=person and (stage="Closed Won" or stage="Closed Lost") and ...}
Use contractStartDate vs closeDate
The template prefers contractStartDate for quarterly bucketing and falls back to closeDate:
(contractStartDate ?: closeDate) >= fiscalQuarterStart()
If your team only tracks closeDate, you can simplify to just closeDate throughout.
---
Key Template Functions
┌───────────────────────────────────────────┬────────────────────────────────────────────────────────┐
│ Function │ What it does │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ fiscalQuarter() │ Returns the current fiscal quarter number │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ fiscalQuarterStart() / fiscalQuarterEnd() │ Start and end dates of a fiscal quarter │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ date("-3m") │ A date 3 months in the past │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ asOf(date, { field }) │ Returns the value of a field as it was on a given date │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ table.opportunity.find{...} │ Queries the opportunity table with filters │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ .count() / .sum{field} │ Aggregates on a result set │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ .sortDesc{field} │ Sorts results by a field descending │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ formatPercent() / formatDate() │ Formatting helpers │
├───────────────────────────────────────────┼────────────────────────────────────────────────────────┤
│ ``` │ │
└───────────────────────────────────────────┴────────────────────────────────────────────────────────┘