Feature Engineering Templates for Customer 360 in Small Business CRMs
Drop-in SQL templates & recipes to turn small-business CRM data into Customer 360 features for segmentation and churn models.
Hook: Stop guessing — derive production-ready customer signals from your small-business CRM
If your analytics team spends weeks stitching CRM exports into spreadsheets and still lacks reliable inputs for segmentation and churn models, this guide is for you. Below are ready-to-use feature engineering recipes and SQL templates you can drop into a dbt model, a Snowflake/BigQuery query, or your ETL job to produce robust Customer 360 features for segmentation and churn prediction.
Why feature engineering for Customer 360 matters in 2026
Small businesses in 2026 operate under tighter privacy rules, composable stacks, and the expectation of near-real-time customer intelligence. Vendors and platforms have matured: lakehouses (Delta/ICEBERG/Hudi), open source feature stores (Feast), and vector engines are now mainstream. But the core challenge remains: small CRMs are sparse, noisy, and schema-inconsistent across vendors. Robust feature engineering converts that messy CRM data into stable, predictive signals that feed segmentation, personalization, and churn models.
Trends to keep in mind (late 2025 – early 2026):
- Real-time feature serving is increasingly expected for in-session personalization.
- Privacy-first design: zero-/first-party data collection and privacy-preserving joins are standard.
- LLMs and vector DBs help extract semantics from support tickets and notes into features.
- Composable analytics: ETL + lakehouse + feature store patterns replace monolith CDPs.
Minimal Customer 360 data model for small-business CRMs
Design a stable minimal model before you build features. These entities are usually present across CRMs:
- accounts: account_id, account_name, created_at, industry, region, ARR/MRR
- contacts: contact_id, account_id, email, role, created_at
- interactions/events: event_id, account_id, contact_id, event_type, amount, created_at
- subscriptions/orders: order_id, account_id, product_id, amount, start_date, end_date, status
- support_tickets: ticket_id, account_id, created_at, resolved_at, priority, sentiment
Important: For small businesses, map contacts to accounts early and use account-level features for churn/segmentation models to avoid sparsity.
Feature engineering recipes & SQL templates
Each recipe includes intent, logic, and a SQL template. Replace placeholders like {{account_id}} and {{events_table}} with your table/column names. These templates use standard ANSI SQL and work with Snowflake/BigQuery/Postgres with minimal edits.
1) Recency, Frequency, Monetary (RFM) — core segmentation inputs
Intent: Basic engagement segmentation and inputs for churn/classification.
-- RFM features per account (30/90/365 day windows)
select
a.account_id,
max(e.created_at) filter (where e.created_at >= date_sub(current_date, interval '30' day)) is not null as recent_30_activity,
count(e.event_id) filter (where e.created_at >= date_sub(current_date, interval '30' day')) as freq_30,
sum(e.amount) filter (where e.created_at >= date_sub(current_date, interval '30' day')) as monetary_30,
count(e.event_id) filter (where e.created_at >= date_sub(current_date, interval '90' day')) as freq_90,
sum(e.amount) filter (where e.created_at >= date_sub(current_date, interval '365' day')) as monetary_365,
datediff('day', max(e.created_at), current_date) as recency_days
from accounts a
left join events e on e.account_id = a.account_id
group by a.account_id;
Notes: Use appropriate date arithmetic for your SQL engine. For BigQuery, replace date_sub/diff functions accordingly.
2) Churn label creation (business-rule)
Intent: Create a conservative, production-ready churn label for supervised learning.
-- Binary churn label: churned if no paid orders in the last 90 days and subscription status != active
with last_paid as (
select account_id, max(start_date) as last_paid_date
from orders
where status = 'paid'
group by account_id
)
select
a.account_id,
case
when last_paid.last_paid_date < date_sub(current_date, interval '90' day) or last_paid.last_paid_date is null then 1
else 0
end as churn_label
from accounts a
left join last_paid on last_paid.account_id = a.account_id;
Tip: For subscription businesses, use end_date and renewal flags. For one-off sales, tune the inactivity window (e.g., 180 days).
3) Decay-weighted recency and trend features
Intent: Capture intensity and direction of engagement—helpful for churn and churn lead scoring.
-- Exponential decay score for events in the last 180 days
with events_window as (
select account_id, created_at,
unix_timestamp(created_at) as ts
from events
where created_at >= date_sub(current_date, interval '180' day)
)
select
account_id,
sum(exp((unix_timestamp(current_date) - ts) / -86400.0 / 30) ) as decay_score -- 30-day half-life tunable
from events_window
group by account_id;
Notes: Replace unix_timestamp and exp functions to match your SQL dialect. The half-life parameter controls memory of past interactions.
4) Support health signals (tickets & sentiment)
Intent: Turn support volume and sentiment into churn predictors.
-- Support features
select
account_id,
count(ticket_id) filter (where created_at >= date_sub(current_date, interval '90' day)) as tickets_90,
avg(case when sentiment is not null then sentiment else 0 end) filter (where created_at >= date_sub(current_date, interval '90' day)) as avg_sentiment_90,
avg(datediff('day', created_at, resolved_at)) filter (where resolved_at is not null and created_at >= date_sub(current_date, interval '90' day)) as avg_resolution_days_90
from support_tickets
group by account_id;
Tip: If sentiment is not available, use LLMs or small classifiers to derive a numeric score from ticket text as a preprocess step (see Vector/LLM section below).
5) Product affinity and cross-sell signals
Intent: Identify strong product interests and cross-sell opportunities.
-- Top product per account and product concentration
with purchases as (
select account_id, product_id, count(*) as cnt, sum(amount) as revenue
from orders
where status in ('paid','completed')
group by account_id, product_id
)
select
p.account_id,
arg_max(product_id, revenue) as top_product_id,
max(cnt) / nullif(sum(cnt) over (partition by account_id),0) as product_concentration
from purchases p
group by p.account_id;
For Snowflake use array_agg or first_value with window functions if arg_max isn't supported.
6) Cohort & lifecycle features
Intent: Assign lifecycle stages and time-since-signup metrics for segmentation.
select
account_id,
min(created_at) as first_seen,
datediff('day', min(created_at), current_date) as days_since_first_seen,
case
when datediff('day', min(created_at), current_date) <= 30 then 'new'
when datediff('day', min(created_at), current_date) <= 180 then 'adopted'
else 'mature'
end as lifecycle_stage
from events
group by account_id;
7) CLTV approximation for small-business customers
Intent: Quick, regular CLTV estimate using historical revenue per account and churn rate.
-- Simple CLTV: avg_monthly_rev * expected_months (1/churn_rate)
with mrr as (
select account_id, sum(amount) as total_revenue, count(distinct date_trunc('month', start_date)) as months_active
from orders
where status in ('paid','completed') and start_date >= date_sub(current_date, interval '365' day)
group by account_id
), churn as (
-- reuse churn label calculation or model-derived churn_rate
select account_id, coalesce(model_churn_rate, 0.05) as churn_rate
from churn_rates
)
select
m.account_id,
(total_revenue / nullif(months_active,0)) as avg_monthly_rev,
(total_revenue / nullif(months_active,0)) * (1.0 / nullif(ch.churn_rate,0.01)) as simple_cltv
from mrr m
left join churn ch on ch.account_id = m.account_id;
Notes: For small samples use Bayesian smoothing on churn_rate; do not trust raw per-account churn rates.
8) Sparse-event smoothing and feature stability
Intent: Avoid noisy features when event counts are low.
-- Laplace / Additive smoothing for ratios
select
account_id,
(sum(success_events)+1.0) / (sum(total_events)+2.0) as success_rate_smoothed
from events
group by account_id;
Use smoothing on rates and log-transform high-skew numeric features (e.g., revenue) before modeling.
9) Text & semantic features from notes and tickets (LLM + vector)
Intent: Convert free text into numeric signals (topic scores, embeddings) for churn and segmentation models.
- Extract embeddings for each ticket/note via an on-prem or cloud LLM/vector encoder (e.g., open-source or managed service).
- Store vectors in a vector DB (Pinecone, Milvus, Weaviate) or as arrays in your lakehouse.
- Aggregate per account: mean-embedding, max-similarity to churn prototypes, topic counts using an LLM classifier.
-- Pseudo-SQL: aggregate precomputed embeddings stored as arrays
select
account_id,
array_avg(embedding) as mean_embedding, -- engine-specific
max(similarity(embedding, :churn_prototype)) as max_churn_sim
from ticket_embeddings
group by account_id;
Privacy note: always anonymize PII before sending text to third-party LLM APIs; prefer local encoders if policy forbids external transmission.
Operational patterns: ETL → Feature Store → Serving
Turn these SQL recipes into reliable signals with a repeatable pipeline:
- Batch ETL: Use dbt models to transform CRM dumps and append to a lakehouse table. Schedule daily runs.
- Feature Store: Push features into a feature store (Feast or a managed equivalent). Register feature definitions, types, and freshness SLA.
- Real-time: For in-session lookups, serve a subset of features in a low-latency store (Redis/online Feast store).
- Monitoring: Implement drift and freshness checks; record feature lineage and model input availability.
Example dbt macro snippet for a reusable windowed aggregation:
{% macro rolling_count(table, account_col, ts_col, days) %}
select
{{ account_col }},
count(*) filter (where {{ ts_col }} >= date_sub(current_date, interval '{{ days }}' day)) as cnt_{{ days }}
from {{ table }}
group by {{ account_col }};
{% endmacro %}
Handling small-business CRM realities
- Sparsity: Aggregate to account-level, smooth ratios, and use hierarchical features (account > contact).
- Multiple contacts: Weight interactions by contact role (decision-maker vs. user) when available.
- Inconsistent schemas: Create a canonical staging schema; map CRM-specific fields into that model in ETL.
- Cost control: Use sampling for heavy text processing; push heavy compute to spot/low-cost clusters; schedule nightly batch jobs for non-real-time features.
Validation and modeling tips
- Use time-aware cross-validation (rolling windows) for churn models.
- Log-transform monetary features; standardize features per-account cohort.
- Feature importance: use permutation importance and SHAP to spot unstable features that correlate with CRM platform artifacts.
- Use calibration and a secondary business-rule guardrail for production churn decisions to protect revenue.
2026-specific recommendations & future-proofing
Design your Customer 360 pipelines with these 2026 realities in mind:
- Privacy-first joins: Implement privacy-preserving record linkage (hashing, bloom filters, PPR) for enrichment sources. See local hosting and privacy-first edge options like pocket edge hosts for designs that keep PII on-device.
- LLM augmentation: Use LLMs to accelerate feature discovery (auto-suggest topics, sentiment), but validate outputs rigorously.
- Vector features: Embeddings add a semantic layer — use them for support-text signals and product-similarity features.
- Lakehouse + Feature Store: Store canonical customer tables in a lakehouse (Delta/Iceberg) and serve features via Feast or cloud-managed feature platforms.
- Observability: Automate freshness/dtype/coverage checks. Track lineage from raw CRM exports to model inputs.
Practical rule: If a feature needs more than one hour of compute per day to update, evaluate whether it truly justifies production cost and latency.
Actionable deployment checklist (30/60/90 days)
- Day 0–30: Define canonical schema, create staging tables, implement RFM & churn label SQL models, start daily ETL runs.
- Day 30–60: Register features in a feature store, deploy a simple churn model with monitoring, add support-ticket sentiment features.
- Day 60–90: Introduce embeddings for notes, add real-time serving for top 10 features, implement drift alerts and SLA checks.
Common pitfalls and how to avoid them
- Overfitting to scarce events: Use smoothing, hierarchical features, and regularization.
- Leaky features: Ensure labels are time-forward and exclude post-label events.
- Untracked transformations: Use dbt and feature store metadata to keep lineage auditable.
- PII leakage: Mask or tokenize PII; apply governance checks before using third-party APIs.
Example: full SQL pipeline snippet (BigQuery-style)
-- Step 1: canonical events window (30/90/365)
create or replace table analytics.account_features as
with events as (
select account_id, event_type, amount, created_at from `project.crm.events`
),
rfm as (
select
account_id,
countif(created_at >= timestamp_sub(current_timestamp(), interval 30 day)) as freq_30,
sum(if(created_at >= timestamp_sub(current_timestamp(), interval 30 day), amount, 0)) as monetary_30,
countif(created_at >= timestamp_sub(current_timestamp(), interval 90 day)) as freq_90,
date_diff(current_date(), max(date(created_at)), day) as recency_days
from events
group by account_id
),
support as (
select account_id, count(*) as tickets_90, avg(sentiment) as avg_sentiment_90 from `project.crm.tickets`
where created_at >= timestamp_sub(current_timestamp(), interval 90 day)
group by account_id
)
select a.account_id, r.* , s.*
from `project.crm.accounts` a
left join rfm r on r.account_id = a.account_id
left join support s on s.account_id = a.account_id;
Final thoughts
Feature engineering is where domain knowledge meets production data engineering. For small-business CRMs, prioritize account-level aggregation, smoothing, and privacy-safe enrichment. Use the SQL templates above as building blocks: start with RFM and churn labels, add support and product signals, then iterate with embeddings and LLM-derived features once your pipeline is stable.
Start small, ship fast: deploy core features in 2–4 weeks, monitor, then expand with semantic features and real-time serving.
Call to action
Ready to operationalize Customer 360 features in your stack? Export these templates into your dbt project or feature store and run a pilot on a 30-day cohort. If you want a tailored checklist and dbt-ready SQL files for your CRM vendor (HubSpot, Zoho, Pipedrive, or custom), contact our team for a 1:1 template pack and pipeline review.
Related Reading
- Serverless Data Mesh for Edge Microhubs: A 2026 Roadmap for Real‑Time Ingestion
- Why AI Shouldn’t Own Your Strategy (And How SMBs Can Use It to Augment Decision-Making)
- Cheat Sheet: 10 Prompts to Use When Asking LLMs
- Pocket Edge Hosts for Indie Newsletters: Practical 2026 Benchmarks and Buying Guide
- AEO for Creators: Optimizing Content for AI Answer Engines (Not Just Blue Links)
- When Celebrities Deny Fundraisers: Legal and Ethical Responsibilities of Organizers
- Salon Tech Stack 2026: From Booking to Broadcast
- Smart Lamps + Speakers: Affordable Ambient Tech to Update Your Flat in Europe
- Designing Apps for Different Android Skins: Compatibility, Performance, and UX Tips
Related Topics
data analysis
Contributor
Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.
Up Next
More stories handpicked for you
