Why Listening Trends Matter

In the previous lesson, you explored how the dashboard interacts with your backend — browsing tracks, logging listens, and viewing recommendations. Now, we shift to a new backend feature: the listening trends API.

  • For users: Trends provide quick insights into their listening habits (mood, tempo, energy).
  • For the smart system: Trends are key for session-aware recommendations, as they help the model adapt to current user preferences.

In this unit, we’ll add a new endpoint, /api/trends/<user_id>, and implement trend analysis in a new session_analysis.py module.

The Core Logic: get_recent_session_trends

The heavy lifting is done by the get_recent_session_trends function in src/session_analysis.py. Its job is to look at a user’s last N sessions (default 5) and extract three key statistics:

  • Most common mood – The mood that appears most frequently in recent tracks.
  • Average tempo – The mean tempo of those tracks.
  • Average energy – The mean energy value (on a 0–1 scale) for the same set.

Code Breakdown

def get_recent_session_trends(user_id: str, N: int = 5) -> dict:
    try:
        sessions_df = pd.read_csv(SESSIONS_FILE_PATH)
    except Exception:
        return {}

    if sessions_df.empty or 'user_id' not in sessions_df.columns:
        return {}

    user_sessions = sessions_df[sessions_df['user_id'] == str(user_id)].copy()
    if user_sessions.empty:
        return {}

    user_sessions['timestamp'] = pd.to_datetime(user_sessions['timestamp'], errors='coerce')
    user_sessions = user_sessions.dropna(subset=['timestamp'])
    user_sessions = user_sessions.sort_values(by='timestamp', ascending=False).head(N)

    moods = []
    tempos = []
    energies = []
    for _, row in user_sessions.iterrows():
        track = get_track_by_id(row['track_id'])
        if not track:
            continue
        mood = track.get('mood')
        tempo = track.get('tempo')
        energy = track.get('energy')
        if mood:
            moods.append(mood)
        if isinstance(tempo, (int, float)):
            tempos.append(tempo)
        if isinstance(energy, (int, float)):
            energies.append(energy)

    if not moods or not tempos or not energies:
        return {}

    common_mood = pd.Series(moods).mode()[0]
    avg_tempo = sum(tempos) / len(tempos)
    avg_energy = sum(energies) / len(energies)

    return {
        'common_mood': common_mood,
        'avg_tempo': avg_tempo,
        'avg_energy': avg_energy
    }

What’s happening here?

  • It reads sessions.csv to get all listening events.
  • Filters only the sessions for the given user_id.
  • Sorts them by time and picks the most recent N sessions.
  • Retrieves each track’s mood, tempo, and energy via get_track_by_id.
  • Calculates the most common mood and averages for tempo and energy.
  • Returns a dictionary like:
{
  "common_mood": "happy",
  "avg_tempo": 102.4,
  "avg_energy": 0.76
}
The Trends API Endpoint

The function is exposed to the frontend through this new route in app.py:

@app.route('/api/trends/<user_id>', methods=['GET'])
def get_user_trends_endpoint(user_id):
    try:
        trends = get_recent_session_trends(user_id)
        if not trends:
            return jsonify({"user_id": user_id, "trends": {}, "message": "No trend data found."}), 200
        return jsonify({"user_id": user_id, "trends": trends})
    except Exception as e:
        return jsonify({"error": "Internal server error"}), 500

Key points:

  • When a GET request hits /api/trends/<user_id>, it fetches trend data for that user.
  • If no sessions are found, it returns an empty trends object with a message.
  • If something goes wrong, it safely returns a 500 error.

Example Request: GET /api/trends/user123

Example Response:

{
  "user_id": "user123",
  "trends": {
    "common_mood": "happy",
    "avg_tempo": 98.7,
    "avg_energy": 0.62
  }
}
Frontend Integration
Summary and Practice Preview

In this lesson, you learned how the Music Player analyzes your recent listening sessions to find trends. You saw how the app collects session data, how the get_recent_session_trends function works, and how the /api/trends/<user_id> endpoint provides this information.

Next, we’ll move toward session-aware recommendations, where these trend metrics will influence which tracks are suggested to the user.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal