You’ve been brought in as “the expert” to develop the algorithm for a personalised recommendation app. The app in question is a Sprig-powered Craft CMS site that suggests travel destination recommendations. Users are presented with photos of places and, based on the photos alone, select whether they would like to visit them or not. With each choice, the algorithm presents a fresh set of recommendations to the user.
Check out the Demo App →
This GitHub repo contains the Craft CMS site that you can spin up with a single command, either locally or in the browser using a GitHub codespace (see the readme file in the repo).
Right now, the recommendations.twig template just returns 3 random destinations, excluding any that have been disliked. Your algorithm should recommend up to 3 destinations to users based on their previous likes and dislikes. All other templates and Sprig components have been set up for you, so the “only” thing you need to do is populate the recommendations
variable using your secret-sauce logic.
Liked and disliked destination IDs are stored in cookies, so recommendations will be user-specific, and users need not be logged in. You can access them in the template using the likeIds
and dislikeIds
Twig variables.
Destinations are tagged with up to 5 tags using an entries field (rather than a tags field, since Entrification is now a thing), which will be the basis for weighting tags and scoring destinations for each individual user.
Destination tags should be assigned a weight based on whether they were liked or disliked, and how many times. So for example, if 3 destinations were liked, all of which were tagged with Beach, and 3 destinations were disliked, 1 of which was tagged with Beach, then Beach would be given a weight of +2
(3 - 1
). If 1 destination tagged with City was liked and 2 were disliked, then City would be given a weight of -1
(1 - 2
)
Finally, destination tags are weighted based on their order in the entries field – the first tag gets the most weight and the last tag gets the least weight. The algorithm should take this into account both when weighting tags (based on an individual user’s likes/dislikes). So if Beach is the first tag in one liked destination, the second tag in another liked destination, and the third tag in two disliked destinations, then it is given a weight of 1x + 1y - 2z
, where x
is the weight of the first tag, y
is the weight of the second tag and z
is the weight of the third tag.
Once each tag has an assigned weight, the algorithm should give each destination a score based on that destination’s weighted tags. Finally, the recommended destinations should be ordered by score descending and should only contain destinations with positive scores (greater than 0
).
For bonus points, make it so that scoring destinations (based on each destination’s tags) also takes the order of the tags in the entries field into account.
While this challenge is tagged “difficult”, it’s still clearly easier than drawing seven red lines, all strictly perpendicular, with red, green and transparent ink.
Your solution should consist of the contents of only the _components/recommendations.twig
template.
_components/recommendations.twig
template. The content structure may not be changed.craft.entries
, etc.) but you can use any of the available parameters on them.