Campaign Analytics
Updated Oct 16, 202515 min read
Analyze campaign performance with comprehensive metrics and insights to optimize your email marketing.
Overview
Campaign analytics allow you to:
- Track email delivery and engagement
- Measure open and click-through rates
- Identify top-performing content and links
- Compare campaign performance over time
- Export data for deeper analysis
- Make data-driven decisions
Understanding your campaign metrics is essential for improving email marketing effectiveness.
Quick Start
View Campaign Report
$ cakemail reports campaign 790
Output:
Campaign: March Newsletter (ID: 790)
Status: sent
Sent: 2024-03-15 10:00:00
=== Delivery Metrics ===
Total Recipients: 1,247
Delivered: 1,189 (95.3%)
Bounced: 58 (4.7%)
Hard Bounces: 45
Soft Bounces: 13
=== Engagement Metrics ===
Opens: 723 (60.8%)
Unique Opens: 567 (47.7%)
Clicks: 234 (19.7%)
Unique Clicks: 189 (15.9%)
Unsubscribes: 12 (1.0%)
=== Performance ===
Open Rate: 47.7%
Click Rate: 15.9%
Click-to-Open: 33.3%
Bounce Rate: 4.7%
Unsubscribe Rate: 1.0%
Core Metrics
Delivery Metrics
Total Recipients:
- Number of contacts campaign was sent to
- Includes all contacts in target list/segment
Delivered:
- Successfully delivered emails
- Excludes hard and soft bounces
- Formula: Total Recipients - Bounces
Bounced:
- Emails that couldn't be delivered
- Hard Bounce: Permanent failure (invalid email)
- Soft Bounce: Temporary failure (inbox full, server down)
# View detailed bounce information
$ cakemail reports campaign 790 -f json | jq '{
total: .total_recipients,
delivered: .delivered,
bounced: .bounced,
hard_bounces: .hard_bounces,
soft_bounces: .soft_bounces,
delivery_rate: (.delivered / .total_recipients * 100 | round)
}'
Output:
{
"total": 1247,
"delivered": 1189,
"bounced": 58,
"hard_bounces": 45,
"soft_bounces": 13,
"delivery_rate": 95
}
Engagement Metrics
Opens:
- Total times campaign was opened
- Includes multiple opens by same contact
- Tracked via invisible pixel
Unique Opens:
- Number of unique contacts who opened
- Each contact counted only once
- More accurate engagement indicator
Open Rate:
- Percentage of delivered emails that were opened
- Formula: (Unique Opens / Delivered) × 100
- Industry average: 15-25%
# Calculate open rate
$ cakemail reports campaign 790 -f json | jq '{
delivered: .delivered,
unique_opens: .unique_opens,
open_rate: (.unique_opens / .delivered * 100 | round)
}'
Clicks:
- Total link clicks in campaign
- Includes multiple clicks by same contact
Unique Clicks:
- Number of unique contacts who clicked
- Each contact counted only once
Click Rate (CTR):
- Percentage of delivered emails with clicks
- Formula: (Unique Clicks / Delivered) × 100
- Industry average: 2-5%
Click-to-Open Rate (CTOR):
- Percentage of openers who clicked
- Formula: (Unique Clicks / Unique Opens) × 100
- Measures content effectiveness
- Industry average: 10-20%
# View click metrics
$ cakemail reports campaign 790 -f json | jq '{
unique_opens: .unique_opens,
unique_clicks: .unique_clicks,
click_rate: (.unique_clicks / .delivered * 100 | round),
ctor: (.unique_clicks / .unique_opens * 100 | round)
}'
Action Metrics
Unsubscribes:
- Contacts who unsubscribed after this campaign
- Important metric for content relevance
Unsubscribe Rate:
- Percentage of delivered emails that unsubscribed
- Formula: (Unsubscribes / Delivered) × 100
- Healthy rate: < 0.5%
- Concerning rate: > 1%
Spam Complaints:
- Contacts who marked email as spam
- Critical metric for sender reputation
- Target: < 0.1%
# View action metrics
$ cakemail reports campaign 790 -f json | jq '{
unsubscribes: .unsubscribes,
unsubscribe_rate: (.unsubscribes / .delivered * 100 | round),
spam_complaints: .spam_complaints,
spam_rate: (.spam_complaints / .delivered * 100 | round)
}'
Viewing Campaign Analytics
Basic Campaign Report
$ cakemail reports campaign 790
JSON Format for Processing
$ cakemail reports campaign 790 -f json > campaign-790.json
Extract Specific Metrics
# Open rate only
$ cakemail reports campaign 790 -f json | jq '.open_rate'
# Top metrics summary
$ cakemail reports campaign 790 -f json | jq '{
name: .campaign_name,
delivered: .delivered,
open_rate: .open_rate,
click_rate: .click_rate,
unsubscribe_rate: .unsubscribe_rate
}'
Multiple Campaign Reports
#!/bin/bash
# report-multiple-campaigns.sh
CAMPAIGNS=(790 791 792)
echo "Campaign | Delivered | Open Rate | Click Rate"
echo "---------|-----------|-----------|------------"
for ID in "${CAMPAIGNS[@]}"; do
REPORT=$(cakemail reports campaign $ID -f json)
NAME=$(echo "$REPORT" | jq -r '.campaign_name' | cut -c1-15)
DELIVERED=$(echo "$REPORT" | jq -r '.delivered')
OPEN=$(echo "$REPORT" | jq -r '.open_rate')
CLICK=$(echo "$REPORT" | jq -r '.click_rate')
printf "%-15s | %9d | %8.1f%% | %9.1f%%\n" "$NAME" $DELIVERED $OPEN $CLICK
done
Link Analytics
View Campaign Links
$ cakemail reports campaign-links 790
Output:
┌────────────────────────────────────────┬────────┬─────────┬─────────┐
│ URL │ Clicks │ Unique │ CTR │
├────────────────────────────────────────┼────────┼─────────┼─────────┤
│ https://example.com/product │ 450 │ 320 │ 26.9% │
│ https://example.com/blog/article │ 230 │ 180 │ 15.1% │
│ https://example.com/special-offer │ 180 │ 150 │ 12.6% │
└────────────────────────────────────────┴────────┴─────────┴─────────┘
Total clicks: 860 (650 unique)
Overall CTR: 54.7%
Top Performing Links
#!/bin/bash
# top-links.sh
CAMPAIGN_ID=$1
cakemail reports campaign-links $CAMPAIGN_ID -f json | \
jq -r '.links | sort_by(-.unique_clicks) | .[0:5][] |
"\(.unique_clicks)\t\(.url)"' | \
column -t -s $'\t'
Export Link Data
$ cakemail reports campaign-links 790 -f json > links-790.json
Time-Based Analytics
Opens Over Time
#!/bin/bash
# opens-over-time.sh
CAMPAIGN_ID=$1
echo "=== Opens Timeline ==="
echo ""
# Get campaign details
CAMPAIGN=$(cakemail campaigns get $CAMPAIGN_ID -f json)
SENT_DATE=$(echo "$CAMPAIGN" | jq -r '.delivered_at')
echo "Campaign sent: $SENT_DATE"
echo ""
# Get current stats
STATS=$(cakemail reports campaign $CAMPAIGN_ID -f json)
echo "Current stats:"
echo " Unique Opens: $(echo "$STATS" | jq -r '.unique_opens')"
echo " Open Rate: $(echo "$STATS" | jq -r '.open_rate')%"
echo ""
echo "Typical open timeline:"
echo " First 24 hours: 50-70% of total opens"
echo " First 48 hours: 70-85% of total opens"
echo " First 7 days: 90-95% of total opens"
Daily Performance Tracking
#!/bin/bash
# track-daily-performance.sh
CAMPAIGN_ID=$1
LOG_FILE="campaign-${CAMPAIGN_ID}-tracking.log"
# Log current metrics
DATE=$(date +%Y-%m-%d-%H:%M:%S)
STATS=$(cakemail reports campaign $CAMPAIGN_ID -f json)
OPENS=$(echo "$STATS" | jq -r '.unique_opens')
CLICKS=$(echo "$STATS" | jq -r '.unique_clicks')
OPEN_RATE=$(echo "$STATS" | jq -r '.open_rate')
CLICK_RATE=$(echo "$STATS" | jq -r '.click_rate')
echo "$DATE,$OPENS,$CLICKS,$OPEN_RATE,$CLICK_RATE" >> $LOG_FILE
echo "Logged: $OPENS opens, $CLICKS clicks"
Schedule with cron:
# Track every 6 hours for first week
0 */6 * * * /path/to/track-daily-performance.sh 790
Comparative Analysis
Compare Two Campaigns
#!/bin/bash
# compare-campaigns.sh
CAMPAIGN_A=$1
CAMPAIGN_B=$2
echo "=== Campaign Comparison ==="
echo ""
# Get reports
REPORT_A=$(cakemail reports campaign $CAMPAIGN_A -f json)
REPORT_B=$(cakemail reports campaign $CAMPAIGN_B -f json)
# Campaign names
NAME_A=$(echo "$REPORT_A" | jq -r '.campaign_name')
NAME_B=$(echo "$REPORT_B" | jq -r '.campaign_name')
echo "Campaign A: $NAME_A (ID: $CAMPAIGN_A)"
echo "Campaign B: $NAME_B (ID: $CAMPAIGN_B)"
echo ""
# Compare metrics
echo "Metric | Campaign A | Campaign B | Difference"
echo "--------------------|------------|------------|------------"
# Open Rate
OPEN_A=$(echo "$REPORT_A" | jq -r '.open_rate')
OPEN_B=$(echo "$REPORT_B" | jq -r '.open_rate')
OPEN_DIFF=$(echo "$OPEN_B - $OPEN_A" | bc)
printf "Open Rate | %9.1f%% | %9.1f%% | %+9.1f%%\n" $OPEN_A $OPEN_B $OPEN_DIFF
# Click Rate
CLICK_A=$(echo "$REPORT_A" | jq -r '.click_rate')
CLICK_B=$(echo "$REPORT_B" | jq -r '.click_rate')
CLICK_DIFF=$(echo "$CLICK_B - $CLICK_A" | bc)
printf "Click Rate | %9.1f%% | %9.1f%% | %+9.1f%%\n" $CLICK_A $CLICK_B $CLICK_DIFF
# Unsubscribe Rate
UNSUB_A=$(echo "$REPORT_A" | jq -r '.unsubscribe_rate')
UNSUB_B=$(echo "$REPORT_B" | jq -r '.unsubscribe_rate')
UNSUB_DIFF=$(echo "$UNSUB_B - $UNSUB_A" | bc)
printf "Unsubscribe Rate | %9.1f%% | %9.1f%% | %+9.1f%%\n" $UNSUB_A $UNSUB_B $UNSUB_DIFF
echo ""
# Winner
if (( $(echo "$OPEN_B > $OPEN_A" | bc -l) )); then
echo "🏆 Campaign B performed better"
else
echo "🏆 Campaign A performed better"
fi
Historical Performance
#!/bin/bash
# historical-performance.sh
LIST_ID=123
echo "=== Historical Campaign Performance ==="
echo ""
# Get all sent campaigns
CAMPAIGNS=$(cakemail campaigns list \
--filter "status==sent" \
--sort "-delivered_at" \
--limit 10 \
-f json | jq -r '.data[].id')
echo "Campaign | Date | Recipients | Open Rate | Click Rate"
echo "---------|------------|------------|-----------|------------"
for ID in $CAMPAIGNS; do
CAMPAIGN=$(cakemail campaigns get $ID -f json)
REPORT=$(cakemail reports campaign $ID -f json)
NAME=$(echo "$CAMPAIGN" | jq -r '.name' | cut -c1-15)
DATE=$(echo "$CAMPAIGN" | jq -r '.delivered_at' | cut -d'T' -f1)
RECIPIENTS=$(echo "$REPORT" | jq -r '.total_recipients')
OPEN=$(echo "$REPORT" | jq -r '.open_rate')
CLICK=$(echo "$REPORT" | jq -r '.click_rate')
printf "%-15s | %10s | %10d | %8.1f%% | %9.1f%%\n" \
"$NAME" "$DATE" $RECIPIENTS $OPEN $CLICK
done
echo ""
# Calculate averages
echo "Calculating averages across all campaigns..."
Month-over-Month Trends
#!/bin/bash
# monthly-trends.sh
YEAR=2024
echo "=== Monthly Campaign Trends - $YEAR ==="
echo ""
echo "Month | Campaigns | Avg Open Rate | Avg Click Rate"
echo "------|-----------|---------------|----------------"
for MONTH in {01..12}; do
START_DATE="$YEAR-$MONTH-01"
# Calculate end date
if [ $MONTH -eq 12 ]; then
END_DATE="$((YEAR + 1))-01-01"
else
END_DATE="$YEAR-$(printf "%02d" $((10#$MONTH + 1)))-01"
fi
# Get campaigns for month
CAMPAIGNS=$(cakemail campaigns list \
--filter "status==sent;delivered_at>=$START_DATE;delivered_at<$END_DATE" \
-f json | jq -r '.data[].id')
if [ -z "$CAMPAIGNS" ]; then
continue
fi
COUNT=$(echo "$CAMPAIGNS" | wc -l)
TOTAL_OPEN=0
TOTAL_CLICK=0
for ID in $CAMPAIGNS; do
REPORT=$(cakemail reports campaign $ID -f json 2>/dev/null)
if [ -n "$REPORT" ]; then
OPEN=$(echo "$REPORT" | jq -r '.open_rate')
CLICK=$(echo "$REPORT" | jq -r '.click_rate')
TOTAL_OPEN=$(echo "$TOTAL_OPEN + $OPEN" | bc)
TOTAL_CLICK=$(echo "$TOTAL_CLICK + $CLICK" | bc)
fi
done
if [ $COUNT -gt 0 ]; then
AVG_OPEN=$(echo "scale=1; $TOTAL_OPEN / $COUNT" | bc)
AVG_CLICK=$(echo "scale=1; $TOTAL_CLICK / $COUNT" | bc)
printf "%5s | %9d | %12.1f%% | %13.1f%%\n" \
"$MONTH" $COUNT $AVG_OPEN $AVG_CLICK
fi
done
Segmentation Analysis
Performance by Segment
#!/bin/bash
# segment-performance.sh
LIST_ID=123
echo "=== Campaign Performance by Segment ==="
echo ""
# Get all segments
SEGMENTS=$(cakemail segments list $LIST_ID -f json | jq -r '.data[] | "\(.id):\(.name)"')
echo "Segment | Campaigns | Avg Open | Avg Click"
echo "-----------------|-----------|----------|----------"
for SEG in $SEGMENTS; do
SEG_ID=$(echo "$SEG" | cut -d: -f1)
SEG_NAME=$(echo "$SEG" | cut -d: -f2- | cut -c1-15)
# Find campaigns sent to this segment
CAMPAIGNS=$(cakemail campaigns list \
--filter "status==sent;segment_id==$SEG_ID" \
-f json | jq -r '.data[].id')
if [ -z "$CAMPAIGNS" ]; then
continue
fi
COUNT=$(echo "$CAMPAIGNS" | wc -l)
TOTAL_OPEN=0
TOTAL_CLICK=0
for ID in $CAMPAIGNS; do
REPORT=$(cakemail reports campaign $ID -f json 2>/dev/null)
if [ -n "$REPORT" ]; then
OPEN=$(echo "$REPORT" | jq -r '.open_rate')
CLICK=$(echo "$REPORT" | jq -r '.click_rate')
TOTAL_OPEN=$(echo "$TOTAL_OPEN + $OPEN" | bc)
TOTAL_CLICK=$(echo "$TOTAL_CLICK + $CLICK" | bc)
fi
done
AVG_OPEN=$(echo "scale=1; $TOTAL_OPEN / $COUNT" | bc)
AVG_CLICK=$(echo "scale=1; $TOTAL_CLICK / $COUNT" | bc)
printf "%-15s | %9d | %7.1f%% | %8.1f%%\n" \
"$SEG_NAME" $COUNT $AVG_OPEN $AVG_CLICK
done
Best Performing Segment
#!/bin/bash
# best-segment.sh
# Find segment with highest average open rate
# (Implementation from segment-performance.sh with sorting)
# Output best segment recommendation
echo "🏆 Best Performing Segment: Premium Users"
echo " Average Open Rate: 62.3%"
echo " Average Click Rate: 28.7%"
echo ""
echo "💡 Recommendation: Prioritize campaigns to this segment"
Key Performance Indicators (KPIs)
Email Deliverability KPIs
#!/bin/bash
# deliverability-kpis.sh
CAMPAIGN_ID=$1
REPORT=$(cakemail reports campaign $CAMPAIGN_ID -f json)
echo "=== Deliverability KPIs ==="
echo ""
# Delivery Rate
TOTAL=$(echo "$REPORT" | jq -r '.total_recipients')
DELIVERED=$(echo "$REPORT" | jq -r '.delivered')
DELIVERY_RATE=$(echo "scale=1; $DELIVERED * 100 / $TOTAL" | bc)
echo "Delivery Rate: $DELIVERY_RATE%"
if (( $(echo "$DELIVERY_RATE >= 95" | bc -l) )); then
echo " ✅ Excellent (target: ≥95%)"
elif (( $(echo "$DELIVERY_RATE >= 90" | bc -l) )); then
echo " ⚠️ Good (target: ≥95%)"
else
echo " ❌ Poor - Clean your list"
fi
echo ""
# Bounce Rate
BOUNCED=$(echo "$REPORT" | jq -r '.bounced')
BOUNCE_RATE=$(echo "scale=1; $BOUNCED * 100 / $TOTAL" | bc)
echo "Bounce Rate: $BOUNCE_RATE%"
if (( $(echo "$BOUNCE_RATE <= 2" | bc -l) )); then
echo " ✅ Excellent (target: ≤2%)"
elif (( $(echo "$BOUNCE_RATE <= 5" | bc -l) )); then
echo " ⚠️ Acceptable (target: ≤2%)"
else
echo " ❌ High - Review list quality"
fi
Engagement KPIs
#!/bin/bash
# engagement-kpis.sh
CAMPAIGN_ID=$1
REPORT=$(cakemail reports campaign $CAMPAIGN_ID -f json)
echo "=== Engagement KPIs ==="
echo ""
# Open Rate
OPEN_RATE=$(echo "$REPORT" | jq -r '.open_rate')
echo "Open Rate: $OPEN_RATE%"
if (( $(echo "$OPEN_RATE >= 20" | bc -l) )); then
echo " ✅ Excellent (industry avg: 15-25%)"
elif (( $(echo "$OPEN_RATE >= 15" | bc -l) )); then
echo " ✓ Good"
else
echo " ⚠️ Below average - Improve subject lines"
fi
echo ""
# Click Rate
CLICK_RATE=$(echo "$REPORT" | jq -r '.click_rate')
echo "Click Rate: $CLICK_RATE%"
if (( $(echo "$CLICK_RATE >= 3" | bc -l) )); then
echo " ✅ Excellent (industry avg: 2-5%)"
elif (( $(echo "$CLICK_RATE >= 2" | bc -l) )); then
echo " ✓ Good"
else
echo " ⚠️ Below average - Improve CTAs"
fi
echo ""
# CTOR
UNIQUE_OPENS=$(echo "$REPORT" | jq -r '.unique_opens')
UNIQUE_CLICKS=$(echo "$REPORT" | jq -r '.unique_clicks')
CTOR=$(echo "scale=1; $UNIQUE_CLICKS * 100 / $UNIQUE_OPENS" | bc)
echo "Click-to-Open Rate: $CTOR%"
if (( $(echo "$CTOR >= 15" | bc -l) )); then
echo " ✅ Excellent (industry avg: 10-20%)"
elif (( $(echo "$CTOR >= 10" | bc -l) )); then
echo " ✓ Good"
else
echo " ⚠️ Below average - Improve content relevance"
fi
List Health KPIs
#!/bin/bash
# list-health-kpis.sh
CAMPAIGN_ID=$1
REPORT=$(cakemail reports campaign $CAMPAIGN_ID -f json)
echo "=== List Health KPIs ==="
echo ""
# Unsubscribe Rate
DELIVERED=$(echo "$REPORT" | jq -r '.delivered')
UNSUBSCRIBES=$(echo "$REPORT" | jq -r '.unsubscribes')
UNSUB_RATE=$(echo "scale=2; $UNSUBSCRIBES * 100 / $DELIVERED" | bc)
echo "Unsubscribe Rate: $UNSUB_RATE%"
if (( $(echo "$UNSUB_RATE <= 0.2" | bc -l) )); then
echo " ✅ Excellent (target: ≤0.5%)"
elif (( $(echo "$UNSUB_RATE <= 0.5" | bc -l) )); then
echo " ✓ Good"
elif (( $(echo "$UNSUB_RATE <= 1.0" | bc -l) )); then
echo " ⚠️ Elevated - Review content relevance"
else
echo " ❌ High - Major content/targeting issues"
fi
echo ""
# Spam Complaint Rate
SPAM=$(echo "$REPORT" | jq -r '.spam_complaints // 0')
SPAM_RATE=$(echo "scale=3; $SPAM * 100 / $DELIVERED" | bc)
echo "Spam Complaint Rate: $SPAM_RATE%"
if (( $(echo "$SPAM_RATE <= 0.1" | bc -l) )); then
echo " ✅ Excellent (target: ≤0.1%)"
else
echo " ❌ Concerning - Review content and list source"
fi
Export and Reporting
Export Campaign Data
#!/bin/bash
# export-campaign-data.sh
CAMPAIGN_ID=$1
OUTPUT_FILE="campaign-${CAMPAIGN_ID}-report-$(date +%Y%m%d).json"
echo "Exporting campaign data..."
# Get campaign details
cakemail campaigns get $CAMPAIGN_ID -f json > campaign-details.json
# Get campaign report
cakemail reports campaign $CAMPAIGN_ID -f json > campaign-report.json
# Get link data
cakemail reports campaign-links $CAMPAIGN_ID -f json > campaign-links.json
# Combine into single file
jq -s '{campaign: .[0], report: .[1], links: .[2]}' \
campaign-details.json \
campaign-report.json \
campaign-links.json > "$OUTPUT_FILE"
# Cleanup
rm campaign-details.json campaign-report.json campaign-links.json
echo "✓ Exported to: $OUTPUT_FILE"
Generate CSV Report
#!/bin/bash
# generate-csv-report.sh
echo "campaign_id,name,date,recipients,delivered,opens,clicks,open_rate,click_rate,unsubscribes" > campaigns-report.csv
# Get all sent campaigns
CAMPAIGNS=$(cakemail campaigns list --filter "status==sent" -f json | jq -r '.data[].id')
for ID in $CAMPAIGNS; do
CAMPAIGN=$(cakemail campaigns get $ID -f json)
REPORT=$(cakemail reports campaign $ID -f json)
NAME=$(echo "$CAMPAIGN" | jq -r '.name' | sed 's/,/_/g')
DATE=$(echo "$CAMPAIGN" | jq -r '.delivered_at' | cut -d'T' -f1)
RECIPIENTS=$(echo "$REPORT" | jq -r '.total_recipients')
DELIVERED=$(echo "$REPORT" | jq -r '.delivered')
OPENS=$(echo "$REPORT" | jq -r '.unique_opens')
CLICKS=$(echo "$REPORT" | jq -r '.unique_clicks')
OPEN_RATE=$(echo "$REPORT" | jq -r '.open_rate')
CLICK_RATE=$(echo "$REPORT" | jq -r '.click_rate')
UNSUBSCRIBES=$(echo "$REPORT" | jq -r '.unsubscribes')
echo "$ID,$NAME,$DATE,$RECIPIENTS,$DELIVERED,$OPENS,$CLICKS,$OPEN_RATE,$CLICK_RATE,$UNSUBSCRIBES" >> campaigns-report.csv
done
echo "✓ Report saved to: campaigns-report.csv"
Best Practices
1. Review Reports Within 24-48 Hours
Most engagement happens in first 48 hours:
# Schedule report review
$ cakemail reports campaign 790 > report-24h.txt
# Review after 24 hours
# Final review after 7 days
2. Track Metrics Over Time
# Log metrics daily for first week
0 12 * * * /path/to/track-daily-performance.sh 790
3. Compare Similar Campaigns
# Compare campaigns to same segment
$ ./compare-campaigns.sh 790 791
4. Focus on Trends, Not Single Campaigns
# Monthly trend analysis
$ ./monthly-trends.sh 2024
5. Set Benchmark Goals
# Document your benchmarks
cat > benchmarks.md << 'EOF'
# Campaign Benchmarks
## Newsletter
- Open Rate Target: 25%
- Click Rate Target: 4%
- Unsubscribe Rate Max: 0.3%
## Promotional
- Open Rate Target: 20%
- Click Rate Target: 8%
- Unsubscribe Rate Max: 0.5%
EOF
6. Investigate Anomalies
# If metrics significantly differ
# Check: Send time, subject line, content, segment, list quality
Troubleshooting
Low Open Rates
Problem: Open rate below 15%
Solutions:
- Improve subject lines (A/B test)
- Check send time
- Verify sender reputation
- Clean inactive subscribers
- Test mobile optimization
Low Click Rates
Problem: Click rate below 2%
Solutions:
- Improve CTA placement
- Make CTAs more prominent
- Verify link destinations work
- Increase content relevance
- Test different content formats
High Unsubscribe Rate
Problem: Unsubscribe rate above 1%
Solutions:
- Review content relevance
- Reduce send frequency
- Improve targeting/segmentation
- Provide preference center
- Check for list purchase/rental
High Bounce Rate
Problem: Bounce rate above 5%
Solutions:
- Clean list regularly
- Remove hard bounces immediately
- Use double opt-in
- Verify email collection process
- Check for spam traps