defmodule BerrypodWeb.SeoController do
use BerrypodWeb, :controller
alias Berrypod.{Pages, Products}
alias BerrypodWeb.R
def robots(conn, _params) do
base = BerrypodWeb.Endpoint.url()
content = """
User-agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Disallow: /users/
Disallow: /webhooks/
Disallow: /checkout/
Sitemap: #{base}/sitemap.xml
"""
conn
|> put_resp_content_type("text/plain")
|> send_resp(200, content)
end
def sitemap(conn, _params) do
base = BerrypodWeb.Endpoint.url()
products = Products.list_products_for_sitemap()
categories = Products.list_categories()
static_pages = [
{R.home(), "daily", "1.0", []},
{R.collection("all"), "daily", "0.9", []},
{R.about(), "monthly", "0.5", []},
{R.contact(), "monthly", "0.5", []},
{R.delivery(), "monthly", "0.5", []},
{R.privacy(), "monthly", "0.3", []},
{R.terms(), "monthly", "0.3", []}
]
category_pages =
Enum.map(categories, fn cat ->
{R.collection(cat.slug), "daily", "0.8", []}
end)
product_pages =
Enum.map(products, fn product ->
images = product_image_entries(product, base)
{R.product(product.slug), "weekly", "0.9", images}
end)
custom_pages =
Pages.list_custom_pages()
|> Enum.filter(& &1.published)
|> Enum.map(fn page -> {"/#{page.slug}", "weekly", "0.6", []} end)
all_pages = static_pages ++ category_pages ++ product_pages ++ custom_pages
entries =
Enum.map_join(all_pages, "\n", fn {path, changefreq, priority, images} ->
image_tags =
Enum.map_join(images, "\n", fn img ->
"""
#{xml_escape(img.url)}
#{xml_escape(img.title)}
"""
|> String.trim_trailing()
end)
url_content =
" #{xml_escape(base <> path)}\n" <>
" #{changefreq}\n" <>
" #{priority}"
if image_tags == "" do
" \n#{url_content}\n "
else
" \n#{url_content}\n#{image_tags}\n "
end
end)
xml = """
#{entries}
"""
conn
|> put_resp_content_type("application/xml")
|> send_resp(200, xml)
end
defp product_image_entries(product, base_url) do
product.images
|> Enum.take(5)
|> Enum.map(fn product_image ->
image = product_image.image
alt_text = product_image.alt_text || product.title
url = "#{base_url}/image_cache/#{image.id}.webp"
%{url: url, title: alt_text}
end)
end
defp xml_escape(nil), do: ""
defp xml_escape(text) when is_binary(text) do
text
|> String.replace("&", "&")
|> String.replace("<", "<")
|> String.replace(">", ">")
|> String.replace("\"", """)
|> String.replace("'", "'")
end
end