Current section
Files
Jump to
Current section
Files
lib/scrivener/html/seo.ex
defmodule Scrivener.HTML.SEO do
@moduledoc """
SEO related functions for pagination. See [https://support.google.com/webmasters/answer/1663744?hl=en](https://support.google.com/webmasters/answer/1663744?hl=en)
for more information.
`Scrivener.HTML.pagination_links/4` will use this module to add `rel` to each link produced to indicate to search engines which
link is the `next` or `prev`ious link in the chain of links. The default is `rel` value is `canonical` otherwise.
Additionally, it helps Google and other search engines to put `<link/>` tags in the `<head>`. The `Scrivener.HTML.SEO.header_links/4`
function requires the same arguments you passed into your `Scrivener.HTML.pagination_links/4` call in the view. However, `header_links` needs
to go into the `<head>` section of your page. See [SEO Tags in Phoenix](http://blog.danielberkompas.com/2016/01/28/seo-tags-in-phoenix.html)
for help with how to do that. The recommended option is to use `render_existing/2` in your layout file and add a separate view to render that.
"""
alias Scrivener.Page
use Phoenix.HTML
@defaults Keyword.drop(Scrivener.HTML.defaults(), [:view_style])
@doc ~S"""
Produces the value for a `rel` attribute in an `<a>` tag. Returns either `"next"`, `"prev"` or `"canonical"`.
iex> Scrivener.HTML.SEO.rel(%Scrivener.Page{page_number: 5}, 4)
"prev"
iex> Scrivener.HTML.SEO.rel(%Scrivener.Page{page_number: 5}, 6)
"next"
iex> Scrivener.HTML.SEO.rel(%Scrivener.Page{page_number: 5}, 8)
"canonical"
"""
def rel(%Page{page_number: current_page}, page_number) when current_page + 1 == page_number,
do: "next"
def rel(%Page{page_number: current_page}, page_number) when current_page - 1 == page_number,
do: "prev"
def rel(_paginator, _page_number), do: "canonical"
@doc ~S"""
Produces `<link/>` tags for putting in the `<head>` to help SEO as recommended by Google webmasters.
Arguments are the same as `Scrivener.HTML.pagination_links/4`. Consider using one of the following techniques to
call this function: [http://blog.danielberkompas.com/2016/01/28/seo-tags-in-phoenix.html](http://blog.danielberkompas.com/2016/01/28/seo-tags-in-phoenix.html)
iex> Phoenix.HTML.safe_to_string(Scrivener.HTML.SEO.header_links(%Scrivener.Page{total_pages: 10, page_number: 3}))
"<link href=\"?page=2\" rel=\"prev\"></link>\n<link href=\"?page=4\" rel=\"next\"></link>"
"""
def header_links(conn, %Page{page_number: 1} = paginator, args, opts) do
next_header_link(conn, paginator, args, opts)
end
def header_links(conn, %Page{total_pages: page, page_number: page} = paginator, args, opts) do
prev_header_link(conn, paginator, args, opts)
end
def header_links(conn, paginator, args, opts) do
{:safe, prev} = prev_header_link(conn, paginator, args, opts)
{:safe, next} = next_header_link(conn, paginator, args, opts)
{:safe, [prev, "\n", next]}
end
def header_links(%Scrivener.Page{} = paginator), do: header_links(nil, paginator, [], [])
def header_links(%Scrivener.Page{} = paginator, opts),
do: header_links(nil, paginator, [], opts)
def header_links(conn, %Scrivener.Page{} = paginator), do: header_links(conn, paginator, [], [])
def header_links(conn, paginator, [{_, _} | _] = opts),
do: header_links(conn, paginator, [], opts)
def header_links(conn, paginator, [_ | _] = args), do: header_links(conn, paginator, args, [])
defp href(conn, paginator, args, opts, page_number) do
merged_opts = Keyword.merge(@defaults, opts)
path = opts[:path] || Scrivener.HTML.find_path_fn(conn && paginator.entries, args)
url_params = Keyword.drop(opts, Keyword.keys(@defaults) ++ [:path])
page_param = merged_opts[:page_param]
params_with_page = url_params ++ [{page_param, page_number}]
args = [conn, merged_opts[:action]] ++ args
apply(path, args ++ [params_with_page])
end
defp prev_header_link(conn, paginator, args, opts) do
href = href(conn, paginator, args, opts, paginator.page_number - 1)
content_tag(:link, [], href: href, rel: rel(paginator, paginator.page_number - 1))
end
defp next_header_link(conn, paginator, args, opts) do
href = href(conn, paginator, args, opts, paginator.page_number + 1)
content_tag(:link, [], href: href, rel: rel(paginator, paginator.page_number + 1))
end
end