Email Engagement Score
Learn how your email engagement score is calculated and how we track opens and clicks
The engagement score measures how actively your subscribers interact with your emails on a scale of 0-100. This score combines open rates and click-through rates to give you a comprehensive view of email performance.
Score Calculation
Your engagement score is calculated from two equally weighted components:
Open Rate Score (50 points maximum)
Target: 30% open rate = 50 points Formula: Each 0.6% open rate = 1 point
The open rate measures the percentage of sent emails that were opened by recipients.
Calculation: openRateScore = Math.min((openRate / 0.6), 50)
Example:
- 30% open rate: 30 / 0.6 = 50 points ✅
- 18% open rate: 18 / 0.6 = 30 points
- 6% open rate: 6 / 0.6 = 10 points
Click Rate Score (50 points maximum)
Target: 10% click rate = 50 points Formula: Each 0.2% click rate = 1 point
The click rate measures the percentage of opened emails that resulted in at least one click.
Calculation: clickRateScore = Math.min((clickRate / 0.2), 50)
Example:
- 10% click rate: 10 / 0.2 = 50 points ✅
- 5% click rate: 5 / 0.2 = 25 points
- 1% click rate: 1 / 0.2 = 5 points
Total Score
Total Engagement Score = Open Rate Score + Click Rate Score
Example Scenarios:
| Open Rate | Click Rate | Open Score | Click Score | Total Score | Rating |
|---|---|---|---|---|---|
| 30% | 10% | 50 | 50 | 100 | Excellent 🟢 |
| 18% | 5% | 30 | 25 | 55 | Good 🔵 |
| 15% | 3% | 25 | 15 | 40 | Fair 🟡 |
| 6% | 1% | 10 | 5 | 15 | Poor 🔴 |
How We Track Opens
Open Tracking Technology
Email opens are tracked using a 1×1 pixel tracking image embedded in the HTML email. When a recipient opens the email and their email client loads images, this pixel sends a signal back to our servers.
Technical details:
- A unique tracking pixel URL is generated for each email
- The pixel is invisible to the recipient (1×1 transparent image)
- When loaded, it triggers a server request that records the open event
- We capture the timestamp, IP address, and user agent
Unique Opens vs. Total Opens
Lumail tracks unique opens only, meaning:
- First open: Counted in metrics
- Subsequent opens: Marked as duplicate and not counted
This is stored in the emailOpen table with an isDuplicate flag:
const uniqueOpensCount = await prisma.emailOpen.count({
where: {
email: { organizationId, createdAt: { gte, lte } },
isDuplicate: false, // Only count unique opens
},
});
Why unique opens?: This prevents inflating your metrics when someone opens an email multiple times.
Open Tracking Limitations
Important: Open tracking is not 100% accurate due to:
- Image Blocking: Some email clients (like Outlook) block images by default
- Privacy Features: Apple Mail Privacy Protection pre-loads images on their servers, not user devices
- Plain Text Emails: Opens cannot be tracked in plain text emails
- Preview Panes: Some clients load images in preview panes, triggering false opens
Typical accuracy: ~70-80% of actual opens are tracked
Apple Mail Privacy Protection Impact
Since iOS 15, Apple Mail pre-loads tracking pixels even if the user never opens the email. This can:
- Inflate open rates for Apple Mail users
- Make timing data unreliable
- Affect A/B testing based on send time
Our approach: We still track these opens but recommend focusing on click rates for Apple Mail-heavy lists.
How We Track Clicks
Click Tracking Technology
All links in your emails are automatically rewritten to route through our tracking servers.
Process:
- Original link:
https://yoursite.com/blog/post - Rewritten link:
https://lumail.io/c/[unique-id] - User clicks → our server records the click → redirects to original URL
What we capture:
- Timestamp of the click
- IP address (for geographic data)
- User agent (device/browser information)
- The specific link clicked
- Which email the click came from
Unique Clicks vs. Total Clicks
Like opens, Lumail tracks unique clicks only:
- First click on any link: Counted in metrics
- Subsequent clicks: Marked as duplicate and not counted
This is stored in the emailClick table:
const uniqueClicksCount = await prisma.emailClick.count({
where: {
email: { organizationId, createdAt: { gte, lte } },
isDuplicate: false, // Only count unique clicks
},
});
Note: A unique click counts the first click per email, regardless of which link was clicked. Multiple clicks on different links in the same email are still marked as duplicates.
Click Rate Calculation
Click rate is calculated as clicks / opens, not clicks / sent:
clickRate = (uniqueClicks / uniqueOpens) × 100
Why?: This measures how engaging your content is to those who opened, giving you actionable insights about email copy and CTAs.
Example:
- Sent: 10,000 emails
- Opened: 2,500 (25% open rate)
- Clicked: 200
- Click rate: 200 / 2,500 = 8% (not 2%)
Unsubscribe Link Tracking
Unsubscribe links are also click-tracked, but they:
- Don't count toward your engagement score
- Are automatically excluded from click rate calculations
- Are still logged for compliance and analytics
Understanding the Metrics
Sent
The total number of emails sent to recipients. This is the baseline for calculating open rate.
Formula: openRate = (uniqueOpens / totalSent) × 100
Opened
The number of unique recipients who opened your email at least once.
Best practice: If your open rate is low (<15%), consider:
- Testing different subject lines
- Sending at different times of day
- Cleaning your list of inactive subscribers
- Improving sender name recognition
Clicked
The number of unique recipients who clicked at least one link in your email.
Best practice: If your click rate is low (<5%), consider:
- Making CTAs more prominent
- Reducing the number of links (fewer options = more clicks)
- Improving email copy and relevance
- Using more compelling action-oriented language
Score Interpretation
| Score Range | Status | Action Required |
|---|---|---|
| 80-100 | Excellent (🟢) | Your emails are highly engaging. Keep doing what works! |
| 60-79 | Good (🔵) | Solid performance. Test improvements to reach excellent. |
| 40-59 | Fair (🟡) | Room for improvement. Focus on subject lines and content. |
| 0-39 | Poor (🔴) | Immediate attention needed. Review content strategy. |
Improving Your Score
Boost Open Rates
-
Craft compelling subject lines
- Use curiosity, urgency, or personalization
- Keep it under 50 characters
- A/B test different approaches
-
Optimize sender name
- Use a recognizable person or brand name
- Avoid "noreply@" addresses
- Stay consistent
-
Send at optimal times
- Test different days and times
- Consider your audience's timezone
- Avoid weekends for B2B
-
Clean your list regularly
- Remove hard bounces immediately
- Consider removing subscribers with no opens in 6+ months
- Use re-engagement campaigns before removing
-
Segment your audience
- Send more relevant content to smaller groups
- Personalize based on interests or behavior
- Avoid one-size-fits-all campaigns
Boost Click Rates
-
Clear call-to-action
- One primary CTA per email
- Make buttons stand out
- Use action-oriented language ("Get Started", not "Click Here")
-
Relevant content
- Match email content to subscriber interests
- Deliver on subject line promises
- Provide immediate value
-
Optimize email design
- Use short paragraphs
- Include plenty of white space
- Make links and buttons easy to tap on mobile
-
Create urgency
- Limited-time offers
- Exclusive content
- Early-bird access
-
Test everything
- A/B test CTA placement
- Try different button colors and sizes
- Test text links vs. buttons
Industry Benchmarks
For context, here are typical industry benchmarks:
| Metric | Excellent | Good | Needs Work |
|---|---|---|---|
| Open Rate | >25% | 15-25% | <15% |
| Click Rate (of opens) | >10% | 5-10% | <5% |
| Engagement Score | >80 | 60-80 | <60 |
Note: Benchmarks vary by industry, audience size, and email type (newsletter vs. promotional). Focus on improving your own metrics over time rather than comparing to others.
Technical Details
The engagement score is calculated using this formula:
function calculateEngagementScore(openRate: number, clickRate: number) {
const openRateScore = Math.min(openRate / 0.6, 50);
const clickRateScore = Math.min(clickRate / 0.2, 50);
return Math.round(openRateScore + clickRateScore);
}
Where:
openRate= (unique opens / total sent) × 100clickRate= (unique clicks / unique opens) × 100
This balanced approach ensures both metrics contribute equally to your overall engagement health.
Related Documentation
- Deliverability Score - Monitor sender reputation
- Content Deliverability Checker - Optimize email content before sending
- Subscriber Events - View open and click events in timeline
- Variables - Personalize emails to boost engagement