Criando um Mapa de Imagens para o Google
28 Dec 2025 (updated: 28 Dec 2025 )
Eu fiz o meu novo Blog, esperei ele ser indexado pelo Google, só que percebi uma coisa: Pouquíssimas imagens haviam sido indexadas. Até que ao pesquisar, vi que faltava uma coisa importante: Um Mapa para o Google encontrar as imagens. E eu precisava resolver isso, já que é um site de artes.
E esse post é sobre como resolvi esse problema, e se você está enfrentando o mesmo problema, pode ser que isso também te ajude.
Encontrando uma Solução e Implementando
E ao buscar por como resolver isso, encontrei uma forma de resolver isso, e foi relativamente fácil fazer com que o Hugo gerasse mais um Sitemap além do sitemap.xml. Primeiro, tive que adicionar algumas linhas no hugo.yaml para poder fazer com que o Sitemap das imagens fosse gerado:
outputFormats:
imagessitemap:
baseName: imagessitemap
mediaType: application/xml
noUgly: true
Mas isso sozinho não faz muita coisa. Sendo assim, tive que adicionar mais uma linha em outro local no mesmo arquivo:
outputs:
home:
- html
- json
- rss
- imagessitemap
Com isso, o Sitemap já estaria sendo gerado. Mas faltava o mais importante: O Leiaute que o Hugo usaria para gerar esse Sitemap. Com isso, eu encontrei duas alternativas.
Dariusz Więckiewicz
O do Dariusz Więckiewicz, foi a primeiro que testei e que implementei no meu Blog. E esse é o código do Dariusz:
{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $limit := .Site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
{{ range where $pages "Sitemap.Disable" "ne" true }}
{{ if or (.Params.featuredImage) (findRE `(?s)<img.+?>` .Content) }}
{{- if .Permalink -}}
<url>
<loc>{{ .Permalink }}</loc>
{{ if .Params.featuredImage }}
{{- $ftimgsrc := "" -}}
{{ if hasPrefix .Params.featuredImage "/" }}
{{ $ftimgsrc = resources.Get .Params.featuredImage }}
{{ else }}
{{ if .Page.BundleType }}
{{ $ftimgsrc = .Page.Resources.GetMatch .Params.featuredImage }}
{{ else }}
{{ $path := path.Join .Page.File.Dir .Params.featuredImage }}
{{ $ftimgsrc = resources.Get $path }}
{{ end }}
{{ end }}
<image:image>
<image:loc>{{ $ftimgsrc.Permalink }}</image:loc>
</image:image>{{ end }}
{{ if (findRE `(?s)<img.+?>` .Content) }}{{ range $k, $_ := findRE `(?s)<img.+?>` .Content }}{{ if $k }}{{ end }}
<image:image>
<image:loc>{{ replaceRE `(?s).*src="(.+?)".*` "$1" . | absURL }}</image:loc>
</image:image>{{ end }}
{{ end }}
</url>{{- end -}}
{{ end }}
{{ end }}
</urlset>
E esse Leiaute se mostrou efetivo: Ele pegou a imagem dos posts definida em .Params.Image no Front Matter de cada postagem, mas que falhou ao incluir as imagens das postagens no Mapa. E isso era um problema pra mim.

Tudo porque, eu salvo as imagens de maneira que as imagens relativas a um post, eu guardo numa pasta images daquele post e as de uso compartilhado, eu salvo em /static/images, para estarem facilmente acessíveis ao escrever outros posts. Por exemplo, usando essa postagem de exemplo, a Imagem do Post estava definida como:
image: /images/desenhos/251227-romeo-alegre.webp
E podemos ver que isso deu muito certo com essa imagem, que está no endereço certo, que seria o http://localhost:1313/images/desenhos/251227-romeo-alegre.webp. Porém, não com as imagens dos posts, que ficaram como http://localhost:1313/images/251227-01.webp ao invés de http://localhost:1313/artes/251227-romeo-alegre/images/251227-01.webp, que seria o endereço correto. E eu queria muito que o Sitemap fosse gerado com tudo.
Hong Xu
E depois, procurei por outra solução, até que encontrei no Discourse do Hugo, uma pessoa chamada Hong Xu, que mostrou um outro Leiaute muito mais simples:
{{- $imageRegex := `.(avif|bmp|gif|jpeg|jpg|png|svg|svgz|webp)$` -}}
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
{{ range where .Site.Pages "Sitemap.Disable" "ne" true }}
{{ $pagePermalink := .Permalink }}
{{ $containsImage := false }}
{{ range .Resources }}
{{ if findRE $imageRegex .Permalink }}
{{ if eq $containsImage false }}
<url>
<loc>{{ $pagePermalink }}</loc>
{{ $containsImage = true }}
{{ end }}
<image:image>
<image:loc>{{ .Permalink }}</image:loc>
</image:image>
{{ end }}
{{ end }}
{{ if eq $containsImage true }}
</url>
{{ end }}
{{ end }}
</urlset>
E testei ele. E ele consegui incluir todas as imagens que estavam no corpo da postagem, mas não a que estava definida no .Params.Image do Front Matter.

Fazendo por mim mesmo
Como eu uso um modo um pouco diferente de colocar as imagens no Blog, os dois modelos não me satisfizeram completamente, pois eu salvo as imagens nas duas maneiras: Na própria pasta do post e na pasta /static/images.
Com isso, tive que implementar uma solução própria, modificando o código de Hong Xu e esse foi o código que implementei no Made by Romeo:
{{- $imageRegex := `.(avif|bmp|gif|jpeg|jpg|png|svg|svgz|webp)$` -}}
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
{{ range where .Site.Pages "Sitemap.Disable" "ne" true }}
{{ if .Params.Image }}
<url>
<loc>{{ .Permalink }}</loc>
<image:image>
<image:loc>{{ .Params.Image | absURL }}</image:loc>
</image:image>
{{ range .Resources }}
{{ if findRE $imageRegex .Permalink }}
<image:image>
<image:loc>{{ .Permalink }}</image:loc>
</image:image>
{{ end }}
{{ end }}
</url>
{{ end }}
{{ end }}
</urlset>
Tudo começa definindo quais seriam os formatos de arquivo que seriam buscados pelo site, com a variável imageRegex. Depois, o cabeçalho do XML é gerado com esse código:
{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
E com isso, vem a lógica, que é essa aqui:
{{ range where .Site.Pages "Sitemap.Disable" "ne" true }}
{{ if .Params.Image }}
<url>
<loc>{{ .Permalink }}</loc>
<image:image>
<image:loc>{{ .Params.Image | absURL }}</image:loc>
</image:image>
{{ range .Resources }}
{{ if findRE $imageRegex .Permalink }}
<image:image>
<image:loc>{{ .Permalink }}</image:loc>
</image:image>
{{ end }}
{{ end }}
</url>
{{ end }}
{{ end }}
Tudo começa com o {{ range where .Site.Pages "Sitemap.Disable" "ne" true }} que apenas considera as páginas que estão habilitadas a entrar no Sitemap. E depois, vai para um {{ if .Params.Image }}, que verifica se aquela página tem uma imagem definida no Front Matter. Se não tiver, essa página será pulada e nada será adicionado.
E se tiver a imagem definida no Front Matter, o link permanente da postagem é colocado no Sitemap com um <loc>{{ .Permalink }}</loc> e a imagem do Front Matter também é adicionada, com esse bloco de comandos.
<image:image>
<image:loc>{{ .Params.Image | absURL }}</image:loc>
</image:image>
Basicamente, o parâmetro .Params.Image é tratado para que seja exibida a URL Absoluta. Ou seja, a URL que leva para aquela imagem. E depois disso, todas as imagens do post são adicionadas no Sitemap, com esse Bloco de comandos:
{{ range .Resources }}
{{ if findRE $imageRegex .Permalink }}
<image:image>
<image:loc>{{ .Permalink }}</image:loc>
</image:image>
{{ end }}
{{ end }}
Aqui é usado o {{ range .Resources }} para exibir todos os recursos daquela página, e depois todos os arquivos são filtrados com o {{ if findRE $imageRegex .Permalink }} usando a variável $imageRegex, e as URLs que levam para essas imagens são incluídas no Sitemap. E esse foi o resultado:

Palavras Finais
Sinceramente estou gostando da experiência de usar o Hugo para os meus Blogs. O que me fez gostar mais dele é a possibilidade de fazer as coisas por mim mesmo, e isso é algo que eu adoro. E também, usar o Hugo me fez aprender mais sobre como um site é feito.
Não que eu não tenha aprendido nada com o WordPress, que é excelente, mas ter algo mais “cru” está me fazendo aprender mais, principalmente para implementar somente as coisas que eu quero.