[008.4] Page-Specific Titles

Page-Specific Titles
[06.13.2017]

Firestorm is coming along nicely. However,
presently each page has the same title. This is a pretty awful user experience,
and it also makes our pages perform poorly in search engines. Let's quickly add
a facility to specify titles for each page in our app.

Project

In the resources section, I've linked to a couple of blog posts that cover
different ways to handle this issue. The posts discuss various considerations
that are great to keep in mind. One of the more compelling points is that the
page's title is really a view-level concern. Consequently, we'll begin by
defining a function on the LayoutView that handles our page titles, and using
it in the app layout:

vim lib/firestorm_web/web/templates/layout/app.html.eex

<!DOCTYPE html><htmllang="en"><head><!-- ... --><!-- We'll pass in the conn so it can be used when
generating the title string --><title><%= page_title(@conn) %></title><!-- ... --></head><!-- ... --></html>

Now we'll add the function to the LayoutView, leaving it static at present:

That works. Next, we'd like to specify a different title for various pages.
We'll begin with the Category controller's index action:

defpage_title(conn)do# Phoenix has a `view_module` function that can determine the view module# that is used for a given connection.## We could define a case statement to segregate by view:casePhoenix.Controller.view_module(conn)doFirestormWeb.Web.CategoryView->"Categories - Firestorm"_->"Firestorm"endend

This works, but of course this case statement will become a bit overbearing. We
could break this into functions in each view module, but as one of the posts
argues, these views are otherwise concerned with rendering the content of the
page, while the layout is concerned with rendering the wrapper, including the
<head> element. With that in mind, let's extract a function in the
LayoutView that takes the view module, the action name, and our connection's
assigns, and returns our preferred title.

Summary

In today's episode, we added custom titles for each of our pages. You can use
this pattern and customize it for your own needs, of course.

There's head-related data other than the title that you will likely want to be
custom on various pages as you build a more complex application. In that case,
it might make sense to define a more broad Metadata module, rather than
PageTitle, and then maybe it makes sense to break it out into
resource-specific modules. For our purposes, what we have will work fine. We'll
cross that bridge when we get there.

sign up for full access

Meet your expert

I've been building web-based software for businesses for over 18 years. In the last four years I realized that functional programming was in fact amazing, and have been pretty eager since then to help people build software better.