We recently completed our first six week cycle here at DEV, and one change I'm particular excited about is making it easier to test and change the way the home page article feed is generated.
First, some background: at the end of January Justin wrote a fantastic deep dive on how the home page article feed is generated. Improving the relevancy of the feed is a big priority for us, but before we could even attempt that there was some housekeeping work to be done. Nick spent a majority of his time this cycle implementing Preact components on the homepage and getting the feed to a place were we (and you!) can make changes to it more easily.
Previously On The Feed
In the past logic to construct the feed existed in both the Rails backend as well as client side JavaScript. StoriesController
made an initial query to get some Article
objects and ordered them, and initializeFetchFollowedArticles.js.erb
did some additional ranking and scoring on that same set of articles. As a result: if one wanted to change the feed to prioritize posts with emojis in their title, changes would need to be made in both StoriesController
as well as initializeFetchFollowedArticles.js.erb
. Depending on which version of the home page feed a user was looking at (the plain feed versus a time based feed, and if the user is logged in or not), changes might need to be made in additional JavaScript files.
Definitely not ideal for rapid change and experimentation: it's no wonder the home page feed composition has been changed infrequently, and only in small amounts.
Getting it Together
To help make it easier to change how the feed is constructed, we've started to consolidate feed generation logic to a service class: Articles::Feed
. Both the legacy StoriesController
and a new controller (Stories::FeedController
) consume the output of this service when rendering the home page article feed. We've usage of the ranking that happens in initializeFetchFollowedArticles.js.erb
from the main home page article feeds for logged in users (the logged out user path and non-preactified feed components still use it. Baby steps!)
TL;DR: if you want to experiment with composition of the home page feed, Articles::Feed
is your one stop shop going forward!
Evaluating Feed Performance
It's not enough to simply change how the feed is generated: the goal is to produce a feed that is more relevant and engaging for users. Ben has implemented Andrew Kane's excellent Field Test gem for A/B Testing. This bit of code in Stories::FeedController
is where a test is selected:
def ab_test_user_signed_in_feed(feed)
test_variant = field_test(:user_home_feed, participant: current_user)
case test_variant
when "base"
feed.default_home_feed(user_signed_in: true)
when "more_random"
feed.default_home_feed_with_more_randomness
when "mix_base_more_random"
feed.mix_default_and_more_random
when "more_tag_weight"
feed.more_tag_weight
when "more_tag_weight_more_random"
feed.more_tag_weight_more_random
else
feed.default_home_feed(user_signed_in: true)
end
end
Each "experiment" gets it's own method in the Articles::Feed
service, and users are routed based on the percentage values in field_test.yml
. Even better: Field Test tracks which users are getting which home page version, and how often those users are visiting the page and commenting on articles. We're using this information to evaluate which variables of the home page are resonating with users. Always bring data to the conversation!
Up Next
In the coming weeks, we'll monitor and continue to adjust the home page feed algorithm. I'd also like to pull even more instances of feed generation into the Articles::Feed
service: feel free to pitch in if you're at all interested!
Happy Coding! ❤️