What lead scoring is (and isn't)#
Lead scoring is a number on each subscriber that tracks how engaged they are with you. It starts at 0; you bump it up when they do something positive (opened, clicked a buy-link, submitted a form), down when they go quiet (no opens for 60 days, unsubscribed from a list).
When the score crosses a threshold, you route them — to a sales tag for a CSM to call, into a higher-frequency cadence for prospect nurture, into a re-engagement automation for a "we miss you" win-back.
The model is simple. The setup in AcelleMail is straightforward. The discipline part — picking the right point values and the right thresholds — that's the marketing call.
Setup in three pieces#
Piece 1: Add a lead_score field to your list#
Audience → [your list] → Fields → New field. Configure:
- Tag (key):
lead_score
- Type: Number
- Default value:
0
- Required at signup: No
This adds a {{ subscriber.lead_score }} merge tag and a per-subscriber numeric value AcelleMail will track + update via automation.
Piece 2: Build automations that bump the score#
Open the visual automation builder#
In AcelleMail's left sidebar, click Automation → Automations. The index lists every automation in this account with its current state:

Click New automation in the top-right toolbar. The trigger picker opens:

This first automation tracks "opened a campaign":
- Trigger: pick Email opened from the trigger picker
- Condition (optional): scope to a specific campaign or "any campaign"
- Action: Update subscriber field →
lead_score = lead_score + 5
Save. The flow now runs every time an open is recorded:

Repeat the pattern for higher-value events. Common point values:
| Event |
Point bump |
Trigger to use |
| Email opened |
+5 |
Email opened |
| Clicked any link |
+10 |
Link clicked (no specific link) |
| Clicked a buy/upgrade link |
+25 |
Link clicked with URL filter on /pricing or /upgrade |
| Submitted a form |
+30 |
Subscribed to list (form's target list) |
| Visited pricing page (via tracker pixel) |
+15 |
Custom event from your site |
| Opened from sequential campaigns 3+ times in 7 days |
+10 bonus |
Compound conditional (see Advanced) |
Piece 3: Build the routing automation#
Once score is being tracked, add a routing automation that watches for threshold crossings.
- Trigger: Field value change on
lead_score
- Condition:
lead_score >= 100
- Action: Add tag →
sales-ready
When you add sales-ready to someone, you can either:
- Email your sales team via a separate automation triggered on tag addition
- Webhook the lead into your CRM via the Send webhook action
- Add to a high-touch nurture list
Verify in the automation index#
The Automations index lists all running flows + their last-run timestamp + total runs:

Click any automation to see its run history + per-subscriber path:

The settings tab shows the configuration + per-run debugging:

Score values that actually mean something#
Don't over-engineer the point values. Start coarse:
| Tier |
Score |
Action |
| Cold |
0-25 |
Default cadence, low frequency |
| Warming |
26-75 |
Bumped to standard cadence + nurture sequence |
| Hot |
76-150 |
Sales-ready tag + CRM handoff |
| Champion |
150+ |
High-touch / CSM outreach |
Adjust quarterly based on what actually correlates with conversion in your funnel. The most useful question to ask each quarter: "of last quarter's converted customers, what was their score 30 days before they converted?" That's your real threshold; ignore the round numbers.
Common pitfalls + fixes#
| Symptom |
Likely cause |
UI fix |
| Scores all stuck at 0 |
The "field update" automation step uses = not lead_score + 5 |
Open the automation step → use "Increment field" mode, not "Set field" |
| Same subscriber scored 50 times for same open |
Open-tracking + automation re-fires per pixel-load (some clients fetch the pixel repeatedly) |
Add a per-day rate limit in the automation conditions: "only run if last_score_update > 24h ago" |
| Score keeps growing forever even for unengaged |
No decay logic |
Add a daily-run scheduled automation that subtracts 1 from everyone's score |
sales-ready tag never gets added despite high scores |
The routing automation uses an old threshold (>= 50) |
Edit the routing automation's condition, re-save |
| Customer-success team complains about wrong-stage leads |
Threshold mis-calibrated |
Audit converted customers' pre-conversion scores; adjust threshold |
Advanced: API-driven scoring from ecommerce, CRM, and product analytics
The AcelleMail automation builder handles the email-side events (open, click, form submit) natively. For non-email events (purchases, app logins, support tickets), you push score updates via the API.
Increment a subscriber's score via API:
ACELLE_TOKEN="..."
ACELLE_LIST_UID="..."
# Get current score
current=$(curl -s -H "Authorization: Bearer $ACELLE_TOKEN" \
"https://acellemail.com/api/v1/subscribers?email=user@example.com&list_uid=$ACELLE_LIST_UID" \
| jq -r '.data[0].fields.lead_score')
new=$((current + 25))
# Update
curl -X PATCH "https://acellemail.com/api/v1/subscribers/{subscriber_uid}" \
-H "Authorization: Bearer $ACELLE_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"fields\": {\"lead_score\": $new}}"
A simpler pattern: use AcelleMail's Custom event trigger + an automation step "Increment field":
# Fire a custom event with the score delta in payload
curl -X POST "https://acellemail.com/api/v1/events" \
-H "Authorization: Bearer $ACELLE_TOKEN" \
-d '{
"subscriber_email": "user@example.com",
"event": "purchase_completed",
"value": 25
}'
Then build an automation triggered by event = purchase_completed → step "Increment lead_score by event.value". One API call, score bumped, all logic in the automation flow.
Shopify integration pattern:
Shopify → Webhook → your bridge service → AcelleMail API. Common point values from Shopify webhooks:
cart_started: +15
cart_abandoned: +5 (after timeout — still engaged)
checkout_completed: +50
order_refunded: -25
The bridge service can be a Cloudflare Worker, an AWS Lambda, a Vercel Edge function — anywhere that maps Shopify's webhook signature to AcelleMail's auth.
Salesforce integration pattern:
Use Salesforce Flow to call AcelleMail's API on Lead status changes:
Lead status → Marketing Qualified: AcelleMail tag "mql" + score +30
Lead status → Sales Qualified: AcelleMail tag "sql" + score +60
Lead converted to Opportunity: AcelleMail tag "opportunity" + score +100
When AcelleMail sees the sales-ready threshold crossing, it can webhook back to Salesforce to create a Task. Two-way sync, both systems agree on the score and the stage.
HubSpot integration pattern:
HubSpot's "contact property" sync via webhook to AcelleMail mirror — when HubSpot's native scoring changes, push the new value to AcelleMail's lead_score field. Single source of truth (HubSpot), AcelleMail just reads the value.
Decay automation (daily-run cron):
# Run via php artisan scheduler or external cron
php artisan tinker --execute='
$subscribers = \App\Model\Subscriber::where("fields->lead_score", ">", 0)->get();
foreach ($subscribers as $s) {
$current = (int) ($s->fields["lead_score"] ?? 0);
$newValue = max(0, $current - 1);
$s->update(["fields" => array_merge($s->fields ?? [], ["lead_score" => $newValue])]);
}
'
OR use AcelleMail's built-in scheduled automation: trigger "Date relative" = "every day at 03:00", action "Decrement field by 1".
Multi-signal scoring — score from multiple sources stays meaningful only if you can debug it. Log every score change with the reason. Store it in a custom field lead_score_log (JSON-encoded array) so a sales rep looking at a hot lead can see why they're hot:
{
"lead_score": 85,
"lead_score_log": [
{"delta": 25, "reason": "shopify.cart_started", "at": "2026-05-10"},
{"delta": 50, "reason": "shopify.checkout_completed", "at": "2026-05-12"},
{"delta": 10, "reason": "email.click", "at": "2026-05-15"}
]
}
This becomes invaluable when investigating "why did this lead score 85?" — without the log, you're guessing.
Related articles#