How I Created an Algorithm for Social Music Discovery
My strategy to getting 4000 users active again and why it failed spectacularly.
What is Brew.fm
Brew.fm is the brainchild of my buddy Bart Proost. At its core, Brew.fm gives you focused music releases by checking and recommending Spotify releases from your favorite artists and the artists in your playlists.
In other words, Bart figured out a way to analyze your Spotify and give you the releases you actually care about.
When I moved to Los Angeles last year, Bart had paused work on Brew and I had my hands empty after Podkast, my podcast snippet-saving app, was rejected by Spotify. Consequentially, I joined Brew to try to get its 4000 users to use the app again.
My immediate hypothesis: if we want to get people using the app again, we need to make it interactive.
Brew.fm suggested music through brews, and I decided to completely revamp them.
What I disliked about Brews
A brew was a set of 5 tracks that another user had as their favorite tracks.
A favorite was a track that made it into a user’s top tracks, which Spotify exposed through its Web API. Spotify allows you to see a user’s top tracks for the past month, 6 months, or for all time.
The 5 tracks we sampled for each brew suggested to a user were sampled from the top tracks of another user who, in their favorites, had a track that the receiving user also had.
What I didn’t like about the brews was that I didn’t know where they were coming from. In other words, I didn’t know which of my favorites was being used as a seed.
And even if I did know, some tracks make it to my favorites even though I don’t really like them that much. Spotify algorithmically introduces tracks into your top rankings based on various factors which I assume include play frequency, track search, and playlist addition.
For example, Free Bird by Lynard Skynard was my #2 track for about a week in March simply because one day I searched for it and listened to it on repeat for 6 hours. I like it, but it’s a one-off that doesn’t necessarily represent my music taste, and I don’t actually want to discover music similar to Free Bird.
Lastly, I didn’t like brews because, sure, I was getting song recs, but if I just wanted song recommendations I would use Spotify with their advanced recommendation algorithm. The unique power Brew.fm had was it gave us access to the music tastes of real people, and we could connect people by showing them from which person a specific recommendation came and what the connection was. I felt the brews were missing interactivity; at the least, let users like a song rec.
I wanted to replicate a phenomenon that happens in record stores.
You start chatting with someone in the record store. You pull up an album you really like. The other person also really likes that album. They recommend you other music you might like since you liked that album.
Boom. A connection made over music. Beautiful.
The Algorithm
The algorithm was essentially a sorting algorithm where the sort is based on the proclivity to a seed track.
We were sorting Brew.fm users based on their proclivity to the track and then sorting their favorite tracks to have the most relevant ones appear first as recommendations to the seed.
Sorting users to a seed track
Brews were recommending tracks from a user who had one of your favorites. The primary connection between you and another user is whether you’ve had the same track as a favorite before.
This is a logical connection, but some connections are more relevant than others. Before we can recommend tracks from a user, we have to find which user to analyze.
It makes sense to sort users based on just how much they’ve liked the seed. However, it would be naive to only look at one point in time. A favorite stays a favorite forever, even if you don’t listen to it this month. That’s why looking at a user’s current top tracks isn’t enough to accurately represent their music preferences.
I decided that an accurate representation of a user’s proclivity to a track is the maximum ranking that track reached for that user. We decided to store these max rankings in topTrackHistory.
How did I build up a user’s topTrackHistory then?
I set up a weekly cron job to retrieve a new batch of top tracks for every user on Brew.fm and updated their proclivities to tracks.
Since we can consider how a track ranks in a user’s topTrackHistory to be their proclivity to the track, we can sort users based on their proclivity to a seed track using their personal rankings.
Sorting favorites for recommendations
Once I was able to sort users to a seed, I needed to decide how I would present their favorites as recommendations.
I could have just returned the tracks sorted by their max ranking for the user i.e. their favorite tracks ever first. It would have been a straightforward approach and not a bad one either.
But I thought there was a better way.
Remember, I was polling our user’s favorites on a weekly basis, in essence creating snapshots in time of their music tastes.
If someone asked me personally for a song rec, I wouldn’t just tell them about all my favorite songs. My taste evolves throughout a single year! We have phases! I’ll have had a month in summer where I went wild on old-school country music, but will have spent all of autumn listening to French indie pop!
Keeping in mind that our users’ music tastes are actually ever-evolving, it seemed logical to first recommend tracks from the same snapshot that contained the seed.
In essence, we’re sorting the various states of an individual user’s music taste as it changed over time in relation to the seed track! Of course, we’ll get duplicates, so we just collapse them:
What we end up with for a particular user is their favorite tracks sorted by proclivity to the seed!
Recap
The main steps of the algorithm:
A seed track as input
Sort Brewfm users by their proclivity to the seed
For each user, sort their past favorites by proclivity to the seed
Return sorted users along with their sorted favorites as recommendations to the seed
Was it successful?
No.
I launched the algorithm as a page within Brew.fm that fetched the user’s current top tracks from Spotify and ran the algorithm for every track. The page showed recommendations gathered from Brew.fm users for the user’s current taste.
Through user analytics, we discovered that few people checked the page out, and when they did, they didn’t spend much time on exploring the recommendations.
We concluded: people don’t really care about the music tastes of strangers.
At least, recommendations don’t mean much unless there’s meaning or sentimentality behind them. We live in an age where we’re constantly flooded with content and recommendations. It’s not like people live in small towns where the closest record store is miles away and only gets 10 new records every week. Nowadays, even if you do live in a small town, with the internet, you have access to everything!
In an age where information and recommendations are abundant, they lose their value. For us to care about a recommendation, there needs to be something underpinning it that enhances its value to us.
When it comes to music, it starts to matter what we get recommended when it comes from a special context.
In other words, I realized music discovery itself isn’t that desired. It’s the social connection made through music sharing that matters most today.
This is why I started working on Cassette.
Moreover, you’ll notice I started this article explaining why I disliked the original brews. In retrospect, I made a huge mistake in focusing on fixing something that I didn’t like instead of the users themselves.
I began an entire initiative based solely on my personal preferences and gut feeling on what Brew.fm was missing. In fact, I had inadvertently ignored what got so many people to sign up for Brew in the first place. It wasn’t music discovery, it was staying up-to-date on your favorite artists’ releases!
The lesson I learned was: don’t do things for the sake of doing them.
What I should have done, since we were trying to get our 4000 users active again, was investigate what persuaded them to sign up so readily and why they paradoxically stopped visiting Brew.fm.
I should've spoken to people before ever touching a line of code.