128 lines
4.2 KiB
Python
128 lines
4.2 KiB
Python
"""
|
|
Analytics routes for email tracking metrics and subscriber engagement.
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify, request
|
|
from services.analytics_service import (
|
|
get_newsletter_metrics,
|
|
get_article_performance,
|
|
get_subscriber_activity_status,
|
|
update_subscriber_activity_statuses
|
|
)
|
|
from database import subscriber_activity_collection
|
|
|
|
analytics_bp = Blueprint('analytics', __name__)
|
|
|
|
|
|
@analytics_bp.route('/api/analytics/newsletter/<newsletter_id>', methods=['GET'])
|
|
def get_newsletter_analytics(newsletter_id):
|
|
"""
|
|
Get comprehensive metrics for a specific newsletter.
|
|
|
|
Args:
|
|
newsletter_id: Unique identifier for the newsletter batch
|
|
|
|
Returns:
|
|
JSON response with newsletter metrics including:
|
|
- total_sent, total_opened, open_rate
|
|
- total_clicks, unique_clickers, click_through_rate
|
|
"""
|
|
try:
|
|
metrics = get_newsletter_metrics(newsletter_id)
|
|
return jsonify(metrics), 200
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
|
|
@analytics_bp.route('/api/analytics/article/<path:article_url>', methods=['GET'])
|
|
def get_article_analytics(article_url):
|
|
"""
|
|
Get performance metrics for a specific article.
|
|
|
|
Args:
|
|
article_url: The original article URL (passed as path parameter)
|
|
|
|
Returns:
|
|
JSON response with article performance metrics including:
|
|
- total_sent, total_clicks, click_rate
|
|
- unique_clickers, newsletters
|
|
"""
|
|
try:
|
|
performance = get_article_performance(article_url)
|
|
return jsonify(performance), 200
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
|
|
@analytics_bp.route('/api/analytics/subscriber/<email>', methods=['GET'])
|
|
def get_subscriber_analytics(email):
|
|
"""
|
|
Get activity status and engagement metrics for a specific subscriber.
|
|
|
|
Args:
|
|
email: Subscriber email address
|
|
|
|
Returns:
|
|
JSON response with subscriber activity data including:
|
|
- status, last_opened_at, last_clicked_at
|
|
- total_opens, total_clicks
|
|
- newsletters_received, newsletters_opened
|
|
"""
|
|
try:
|
|
# Get current activity status
|
|
status = get_subscriber_activity_status(email)
|
|
|
|
# Get detailed activity record from database
|
|
activity_record = subscriber_activity_collection.find_one(
|
|
{'email': email},
|
|
{'_id': 0} # Exclude MongoDB _id field
|
|
)
|
|
|
|
if activity_record:
|
|
# Convert datetime objects to ISO format strings
|
|
if activity_record.get('last_opened_at'):
|
|
activity_record['last_opened_at'] = activity_record['last_opened_at'].isoformat()
|
|
if activity_record.get('last_clicked_at'):
|
|
activity_record['last_clicked_at'] = activity_record['last_clicked_at'].isoformat()
|
|
if activity_record.get('updated_at'):
|
|
activity_record['updated_at'] = activity_record['updated_at'].isoformat()
|
|
|
|
return jsonify(activity_record), 200
|
|
else:
|
|
# Return basic status if no detailed record exists yet
|
|
return jsonify({
|
|
'email': email,
|
|
'status': status,
|
|
'last_opened_at': None,
|
|
'last_clicked_at': None,
|
|
'total_opens': 0,
|
|
'total_clicks': 0,
|
|
'newsletters_received': 0,
|
|
'newsletters_opened': 0
|
|
}), 200
|
|
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|
|
|
|
|
|
@analytics_bp.route('/api/analytics/update-activity', methods=['POST'])
|
|
def update_activity_statuses():
|
|
"""
|
|
Trigger batch update of subscriber activity statuses.
|
|
|
|
Updates the subscriber_activity collection with current engagement
|
|
metrics for all subscribers.
|
|
|
|
Returns:
|
|
JSON response with count of updated records
|
|
"""
|
|
try:
|
|
updated_count = update_subscriber_activity_statuses()
|
|
return jsonify({
|
|
'success': True,
|
|
'updated_count': updated_count,
|
|
'message': f'Updated activity status for {updated_count} subscribers'
|
|
}), 200
|
|
except Exception as e:
|
|
return jsonify({'error': str(e)}), 500
|