Skip to main content
GUIDE · ANALYTICS11 min read

LTV RFM: setup and segment interpretation

TrackLayer computes RFM (Recency, Frequency, Monetary) scores every night and maps every customer to one of five segments. This guide shows marketers and analysts how the score is calculated, how to navigate the dashboard, and how to build re-engagement campaigns from at-risk segments.

Phase 7.4

What RFM is

RFM is a customer segmentation framework that scores purchase behavior in three dimensions. Recency measures how recently a customer bought — recent buyers are more likely to buy again than lapsed ones. Frequency measures how often they buy — regular buyers signal loyalty. Monetary measures how much they spend — high-value customers deserve different treatment than low-value ones.

TrackLayer assigns quintile scores (1 to 5) in each dimension. Quintile 5 is the best: most recent, most frequent, or highest spend. The three quintile scores combine into a composite score from 1 to 100, where 100 is the theoretical best customer on all three dimensions. The composite score maps to a named segment.

# Example: customer c_44f8
recency_score   = 4   # purchased 23 days ago — recent
frequency_score = 5   # 12 purchases in last 365d — very frequent
monetary_score  = 4   # €2,340 total spend — high value

# Composite score = weighted sum
rfm_score = (recency × 0.35) + (frequency × 0.40) + (monetary × 0.25)
          = (4 × 0.35) + (5 × 0.40) + (4 × 0.25)
          = 1.40 + 2.00 + 1.00 = 4.40
composite = round(4.40 × 20) = 88  →  segment: champion
Computation

How TrackLayer computes it

A nightly cron job runs at 04:30 UTC against the customer_ltv table. It evaluates all user_keys with at least one purchase event in the trailing 365-day window. The computation window slides daily so scores always reflect the most recent full year.

Dimension calculation

  • Recency: Days since most recent purchase event for that user_key. Quintile boundary computed across all customers within the merchant — most recent buyer gets 5.
  • Frequency: Count of distinct purchase events in 365d. More purchases → higher quintile. Customers with only 1 purchase can still score 2–3 if the frequency distribution is skewed low.
  • Monetary: Sum of purchase values in 365d, converted to USD before ranking. EUR × 0.92, GBP × 1.18, other currencies × 1.0.

Composite score formula

rfm_score = (recency_quintile × 0.35)
          + (frequency_quintile × 0.40)
          + (monetary_quintile × 0.25)

# Scale to 1–100
composite_score = round(rfm_score × 20)

# Segment mapping
81–100  → champion
61–80   → loyal
41–60   → at_risk
21–40   → lost
0–20    → new

Frequency gets the highest weight (0.40) because repeat buyers are the strongest retention signal. Monetary is 0.25 — lower than recency — so a customer who spent significantly in the past but lapsed is correctly flagged as at-risk rather than classified as champion.

Dashboard

How to read the dashboard

Navigate to /insights/ltv. The page opens with a summary bar showing five tiles: total customers scored, champion percentage, at-risk count, average predictive LTV, and the 30-day LTV trend.

Total customers scoredCount of unique user_keys with at least one purchase in the last 365d
Champion %Share of scored customers in the Champion segment
At-risk countAbsolute number of at_risk customers requiring campaign action
Avg predictive LTVMean of the predictive_ltv column across all customers
LTV trend (30d)Change in aggregate monetary value across segments vs prior 30d window

Below the summary tiles is a sortable customer table: user_key, email (hashed, not plaintext), segment badge, rfm_score, and predictive_ltv. Click any row to open the drill-down at /insights/ltv/[user_key].

Drill-down: /insights/ltv/[user_key]

The customer profile page shows the full purchase timeline: every order with date, currency, converted amount, and event_id. Below the timeline is a segment trajectory chart (Phase 8.6) — a line plot of rfm_score over the last 90 days. This tells you whether the customer is trending up (toward champion) or sliding toward at_risk or lost.

# /insights/ltv/c_44f8 — example drill-down

Purchase timeline (last 365d):
  2026-04-12  €89.00   →  $81.88   order_9912
  2026-03-28  £45.00   →  $53.10   order_9856
  2026-02-10  €124.00  →  $114.08  order_9701
  ...

Segment trajectory (last 90d):
  Apr 23 → 88 (champion)
  Apr 16 → 85
  Apr 09 → 81
  Apr 02 → 77  ← product returns caused score dip
  Mar 26 → 79
  ...

Current score: 88 · segment: champion
Predictive LTV: $3,240
Playbook

At-risk action playbook

The at_risk segment (score 41–60) is your highest-priority campaign target. These customers bought recently and valued your product enough to buy multiple times, but their recency or frequency has dropped. The window to win them back is narrow — a customer at score 41 today may be at 35 next month without intervention.

Identify at-risk customers

In /insights/ltv, sort the customer table by segment and filter to at_risk. Export the CSV with the export button. The file includes email (for Mailchimp or Klaviyo import), score, and predictive_ltv. Filter for score > 35 and predictive_ltv > your CAC recovery threshold — do not spend on customers where LTV is lower than the cost to re-engage.

Trigger a re-engagement campaign

The real example: a DTC brand identifies 340 at-risk customers with score > 38 and predictive_ltv > $180. They import the list as a static segment in Klaviyo, then create a 3-email sequence: a personalized product recommendation (using their most purchased category), a limited-time offer tied to their last product, and a final win-back message with a deeper discount.

In Mailchimp, use the same export. Create a customer segment in Mailchimp E-commerce from the imported audience, then trigger a automation flow with the same cadence. Track the conversion rate per email and the recovered LTV against campaign cost.

# Re-engagement campaign — expected outcomes
at_risk list size:          340 customers
avg predictive LTV:         $210
re-engagement conversion:  ~8% (27 customers)
recovered revenue:         27 × $210 = $5,670
campaign cost (Klaviyo):   ~$120 (3 emails × 340 × $0.0001)
net recovered revenue:     $5,550
Formula

Predictive LTV formula

The composite RFM score is descriptive — it tells you where the customer is. Predictive LTV tells you where they are going. The formula is:

predictive_ltv = monetary × frequency_decay × cohort_factor

# monetary
Average order value × estimated number of future orders.
Based on trailing 365d monetary_total and frequency_count.

# frequency_decay
Exponential decay penalizes long gaps between purchases.
Decay rate: 0.95^(gap_days / 30) — 30-day gap → 0.95 multiplier.
A customer who bought 90 days ago gets more penalty than one
who bought 15 days ago.

# cohort_factor
Customers acquired more recently have a higher forward factor
because their purchase history is incomplete — they may be
early in the relationship. Customers acquired >18 months ago
have a lower factor (cap at 0.85×).

Example:
  monetary:     $1,240
  gap_days:     42  →  decay = 0.95^(42/30) = 0.89
  cohort:       acquired 4 months ago  →  factor = 0.92

  predictive_ltv = 1240 × 0.89 × 0.92 = $1,015

The predictive_ltv column is stored in customer_ltv and updated on every cron run. Use it to prioritize acquisition spend — a customer with $2,000 predictive LTV and a $400 CAC means 5× ROI potential, not a 2×.

Phase 8.6

Segment trajectory tracking

customer_ltv_history stores a snapshot of the customer record on every cron run. The snapshot includes rfm_score, segment, and predictive_ltv. Querying this table gives you the score trajectory over any time window.

-- customer_ltv_history — simplified
CREATE TABLE customer_ltv_history (
  id            BIGSERIAL PRIMARY KEY,
  user_key      TEXT    NOT NULL,
  snapshot_at    TIMESTAMPTZ NOT NULL,
  rfm_score     INTEGER,
  segment       TEXT,
  predictive_ltv NUMERIC(10,2),
  monetary      NUMERIC(10,2),
  frequency     INTEGER,
  recency_days  INTEGER
);
-- Indexed on (user_key, snapshot_at) for fast trajectory queries

-- Trajectory: last 90 days for customer c_44f8
SELECT snapshot_at, rfm_score, segment
FROM customer_ltv_history
WHERE user_key = 'c_44f8'
  AND snapshot_at > now() - INTERVAL '90 days'
ORDER BY snapshot_at ASC;

The /insights/ltv/[user_key] page renders this data as a line chart. Use the trajectory to correlate score changes with campaign actions: a campaign that drove a conversion 5 days ago should show a score increase at the next cron run.

FAQ

FAQ

How is the RFM quintile score computed?

Recency: days since last purchase — the most recent buyer gets 5, oldest gets 1. Frequency: total order count — most frequent gets 5, least gets 1. Monetary: total spend — highest spender gets 5, lowest gets 1. Each dimension is independently ranked within the merchant's customer base. Quintile boundaries are recomputed nightly.

What currency conversion rates are used?

EUR → USD: 0.92. GBP → USD: 1.18. All other currencies default to 1.0 (USD natively). Rates are applied to the monetary component before quintile ranking. They are static rates, not live FX — updated manually when significant shifts occur.

What if a customer has only one purchase?

A single purchase still gets a score. Recency is computed from that purchase date. Frequency is set to 1 (quintile 1 or 2 depending on the merchant's frequency distribution). Monetary uses the single transaction amount. The predictive LTV formula accounts for low-frequency customers with the frequency_decay multiplier.

Can I export the segment list to Mailchimp or Klaviyo?

Yes. The /insights/ltv dashboard has an export button that downloads a CSV of user_key, email, segment, rfm_score, and predictive_ltv. Import this as a static segment in Mailchimp or Klaviyo, then trigger an automation for at_risk customers.

How does segment trajectory work?

customer_ltv_history (Phase 8.6) stores a snapshot of rfm_score and segment on every cron run. You can query the history table to see a customer's score at each point in time. The /insights/ltv/[user_key] page renders this as a line chart showing score trend over the last 90 days.

When does the score next update after I act on it?

The next nightly cron runs at 04:30 UTC. If a customer converts as part of your re-engagement campaign, their next score will reflect the new purchase at the next run. Allow 24–48 hours for score updates to reflect campaign-driven conversions.

Continue

Next reads

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.