If users feel remembered and valued when they visit our website, they're more likely to return. We could, theoretically, keep a database tracking users' preferred currency conversions or frequently checked weather locations and show these by default. However, making users log in every time would likely deter them due to the hassle.
This is where HTTP cookies come in handy. Think of cookies as digital Personal Assistants that live on users' computers. They remember certain information from previous visits (like preferred settings) and communicate this back to us automatically when the user returns. This approach has its downsides—for example, we don’t control the cookies on the user's device, and they can be deleted or lost if the user switches devices or browsers. Despite these issues, cookies are widely used because they simplify user experience without the need for databases or mandatory logins.
1 - Why Cookies
Our application is facing a couple of usability issues. Let’s take an example with a user named Bob from Toronto. Bob visits our site and by default sees weather for London, headlines from BBC. Interested in local weather, Bob searches for Toronto in the Weather search bar and hits Enter. He finds out it’s the usual cold and rainy day in Seattle, which is a bit of a downer, so he scrolls down for some distraction and switches the news feed from BBC to CNN. After reading a few uninspiring headlines, Bob looks back up, hoping for something cheerier, but now the weather has flipped back to gloomy London. Here’s what’s going wrong:
Not remembering our users' choices even while they stay on our site
Not remembering our users' choices after they close our site and revisit at a later stage
2 - Setting Cookies with Flask
Flask really simplifies working with cookies. To get started, we need a couple of extra tools. First, we'll bring in the datetime library from Python, which will help us decide how long our cookies should last. Then, we'll use Flask’s make_response() function to create a response object that lets us manage cookies easily. Just add these two lines to the imports section of your main.py file:
import datetime
from flask import make_response
Earlier, we were just putting together our web page with some custom details and sending it straight to users. But if we want to add cookies, there's an extra step involved:
We create a response object using the make_response() function
Then, we send the whole package—web page and cookie—back to the user
Here’s how you can change the end of the get_news_and_weather function in headlines.py to make this happen:
response = make_response(render_template("home.html", articles=feed["entries"], weather=weather))
expires = datetime.datetime.now() + datetime.timedelta(days=365)
response.set_cookie("publication", publication, expires=expires)
response.set_cookie("city", city, expires=expires)
return response
The make_response section of the app does two important things: it builds the page you see and saves your preferences using cookies. It starts by using the make_response function to create a response with the rendered home.html template, which includes the news articles and weather information you requested. Next, it calculates an expiration date for the cookies by adding 365 days to the current date using datetime.timedelta. The set_cookie method is then used to attach two cookies to the response: one for your selected city and another for your chosen news source, with both set to expire after a year.
When the app runs return response, it sends this modified response back to your browser. The browser stores the cookies alongside the webpage. On your next visit, the app uses these cookies to automatically load your saved preferences, such as the city for weather updates and your preferred news source
If you use the brave browser, you can actually see all of your stored cookies here: brave://settings/content/all
3 - Retrieving Cookies
Remembering user information with cookies is only useful if we actually use that info. So after setting cookies right before we send a response, we also need to check for these cookies whenever a user visits our site again. If you recall how we retrieved named arguments from Flask’s request object, fetching cookies works in a similar way.
Here’s how you can grab a cookie named publication if it’s been set:
request.cookies.get("publication")
This process is pretty straightforward. The only part that needs careful handling is the fallback logic. Generally speaking, we always prioritize the user's current choices over everything. So, if a user types something in or picks an option from a drop-down menu, that's what we go with, no matter what they've done in the past. If there isn't a fresh input or choice this visit, then we check the cookies to see if there's a stored preference we can use. And if the cookies don't tell us anything either, then we fall back to the default settings we've hard-coded into the app.
4 - Fallback logic
Let’s focus on getting this logic set up for the publication option first. In the get_news_and_weather() function in your main.py file, add a new if statement to handle the publication logic, and make sure it looks something like this:
# get customised headlines, based on user input or default
publication = request.args.get("publication")
if not publication:
publication = request.cookies.get("publication")
if not publication:
publication = DEFAULTS["publication"]
Now, we're setting up our site to first check the GET arguments for user inputs, then use any relevant cookies if the GET arguments aren't there, and finally, use a default setting if neither is available. Let's see how this works in action:
Open your web browser and head to localhost:1234. Try searching for 'Fox' in the Publication search bar and wait for the page to reload showing Fox News headlines. After that, close your browser, then reopen it and visit localhost:1234 again. This time, you should automatically see the Fox headlines without having to search again, even though there's no publication argument in the URL. This shows that the cookie saved your last choice and the site remembered it on your return.