""" 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/', 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/', 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/', 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