Introduction: Why User Listening History Matters

Welcome back! In the previous lessons, you learned how to set up a backend for a music player app, serve track data, and log when a user listens to a track. Now, let’s take the next step: accessing and displaying a user’s listening history.

Showing users their listening history is a key feature in most music apps. It helps users remember what they have listened to, discover patterns in their listening habits, and even get personalized recommendations. In this lesson, you will learn how to retrieve and display this history using the data we have been collecting.

Quick Recap: App and Data Structure

Before we dive in, let’s quickly remind ourselves of the app’s structure and the data files involved. You have already set up:

  • A tracks.json file that stores information about all available tracks.
  • A sessions.csv file that logs each time a user listens to a track.

Here’s a quick look at how these are loaded and used in the app:

import pandas as pd
import os

TRACKS_FILE_PATH = os.path.join(os.path.dirname(__file__), '..', 'static', 'tracks.json')
SESSIONS_FILE_PATH = os.path.join(os.path.dirname(__file__), '..', 'static', 'sessions.csv')

# Load all tracks
tracks_df = pd.read_json(TRACKS_FILE_PATH)

# Load all listening sessions
sessions_df = pd.read_csv(SESSIONS_FILE_PATH)

This code shows how we use Pandas to read both the track and session data. We will use these dataframes to find and display a user’s listening history.

How We Store and Find Listening Sessions

Whenever a user listens to a track, we log that session in the sessions.csv file. Each row in this file represents one listening event and contains the following columns:

user_idtrack_idtimestamp
11012024-06-01T10:00:00
21022024-06-01T10:05:00
11032024-06-01T10:10:00

To get a specific user’s listening history, we need to filter this file for their user_id. Here’s how this is done in the code:

def get_user_listening_history(user_id):
    """
    Retrieves listening history for a specific user.
    Returns DataFrame with user's sessions or empty DataFrame.
    """
    if not os.path.exists(SESSIONS_FILE_PATH):
        return pd.DataFrame()
    
    try:
        sessions_df = pd.read_csv(SESSIONS_FILE_PATH)
        if 'user_id' not in sessions_df.columns:
            return pd.DataFrame()
        
        # Filter sessions for specific user
        user_sessions = sessions_df[sessions_df['user_id'] == str(user_id)]
        return user_sessions
    except Exception:
        return pd.DataFrame()

Explanation:

  • The function checks if the sessions file exists.
  • It loads the sessions into a DataFrame.
  • It filters the DataFrame to include only rows where user_id matches the given user.
  • If anything goes wrong, it returns an empty DataFrame.

Example Output:
If you call get_user_listening_history("1"), you might get:

user_idtrack_idtimestamp
11012024-06-01T10:00:00
11032024-06-01T10:10:00
Serving Listening History With An API Endpoint

To make this listening history available to the frontend or other services, we expose it through an API endpoint. Here’s the relevant part of the code:

from flask import Flask, jsonify
from src.database import get_user_listening_history

app = Flask(__name__)

@app.route('/api/history/<user_id>', methods=['GET'])
def get_history_endpoint(user_id):
    """API endpoint to retrieve user's listening history."""
    history_df = get_user_listening_history(user_id)
    
    history_list = history_df.to_dict(orient='records') if not history_df.empty else []
    
    return jsonify({
        "user_id": user_id,
        "history": history_list
    })

Explanation:

  • The endpoint /api/history/<user_id> accepts a user ID as part of the URL.
  • It calls the get_user_listening_history function to get the user’s sessions.
  • The result is converted to a list of dictionaries (one per session).
  • The API returns a JSON object with the user ID and their listening history.

Sample API Response:

{
  "user_id": "1",
  "history": [
    {
      "user_id": "1",
      "track_id": "101",
      "timestamp": "2024-06-01T10:00:00"
    },
    {
      "user_id": "1",
      "track_id": "103",
      "timestamp": "2024-06-01T10:10:00"
    }
  ]
}

This makes it easy for any client (like a web or mobile app) to display the user’s listening history.

Detailed Listening History with Track Metadata

Right now, your listening history only shows user ID, track ID, and timestamps. But wouldn’t it be more useful to also show track info — like title, artist, and genre?

Let’s upgrade your API to include full metadata. Here’s how it works:

# database.py
def get_detailed_listening_history(user_id):
    """
    Returns a user's listening history with full track metadata joined in.
    """
    if not os.path.exists(SESSIONS_FILE_PATH):
        return []
    
    try:
        sessions_df = pd.read_csv(SESSIONS_FILE_PATH)
        tracks_df = pd.read_json(TRACKS_FILE_PATH)
        
        user_sessions = sessions_df[sessions_df['user_id'] == str(user_id)]
        merged = user_sessions.merge(tracks_df, how='left', left_on='track_id', right_on='id')
        
        return merged.to_dict(orient='records')
    except Exception:
        return []

This version merges the listening logs with the full track list from tracks.json.

In the app.py, add this new route:

from src.database import get_detailed_listening_history

@app.route('/api/history/<user_id>/detailed', methods=['GET'])
def get_detailed_history_endpoint(user_id):
    """API endpoint to get full listening history with track metadata."""
    history = get_detailed_listening_history(user_id)
    return jsonify({
        "user_id": user_id,
        "detailed_history": history
    })

Now a request to curl -s http://localhost:5001/api/history/user123/detailed might return:

{
  "user_id": "user123",
  "detailed_history": [
    {
      "user_id": "user123",
      "track_id": "track001",
      "timestamp": "2024-06-01T10:00:00",
      "title": "Sunrise Melody",
      "artist": "Synth Weaver",
      "album": "Digital Dreams"
    },
    ...
  ]
}

This is what powers the "Recently Played" screens you see in real music apps.

Summary And Practice Preview

In this lesson, you learned how to access and display a user’s listening history by:

  • Filtering session data for a specific user.
  • Returning the results through a dedicated API endpoint.

This is a key feature for any music app, helping users keep track of what they have listened to. You are now ready to practice these skills and build on what you have learned.

Congratulations on reaching the end of this course! You have built a solid foundation for handling music data and session tracking. Keep experimenting and applying these concepts to your own projects!

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