# Collecting values over a site (using .Site.Store?)

**URL:** <https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816>\
**Category:** support\
**Created:** [May 21, 2025, 1:51am UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816 "2025-05-21T01:51:10Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![gleicher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/gleicher/32/11543_2.png) [@gleicher](https://discourse.gohugo.io/u/gleicher)\
**Post date:** [May 21, 2025, 1:51am UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/1 "2025-05-21T01:51:10Z")

</div>

What I want to do: have a shortcode that adds itself to a list/map - and have that map displayed on a page (with a list of all the “things” on one page).

Is there a good way to do it?

I almost know one way: I could use `.Site.Store.SetInMap` to put things into a map. And I can read stuff out of the map.

But… the thing I don’t know how to do:  
Force the page that I want the “result” to be on to be the last one built (so all the other pages have put their stuff into the map first).

As far as I know, there is no way to control the order in which pages are built, so some lucky page is last, and would have the complete list. Other pages will only have the information from the pages that were rendered before it.

Is there either (1) some way to designate a page to be built last (so my scheme of using .Site.Store would work) or (2) some better way to do this?

---

<div class="post-metadata">

**Author:** ![irkode](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/irkode/32/26135_2.png) [@irkode](https://discourse.gohugo.io/u/irkode)\
**Post date:** [May 21, 2025, 5:14am UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/2 "2025-05-21T05:14:12Z")

</div>

right from the bat I would go with:

- a dedicated template for that _last_ page
- within that template use [templates.Defer](https://gohugo.io/functions/templates/defer/#article)

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [May 22, 2025, 2:36pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/3 "2025-05-22T14:36:41Z")

</div>

@gleicher

The optimal approach may depend on what you are collecting and how you are presenting it.

For example, are you collecting one or more snippets of content? For example:

```plaintext
{{% thing %}}
This is **thing** one on Post 1.
{{% /thing %}}

{{% thing %}}
This is **thing** two on Post 1.
{{% /thing %}}

```

And when listing these, do you want to include a link to the locations from which they were collected?

---

<div class="post-metadata">

**Author:** ![gleicher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/gleicher/32/11543_2.png) [@gleicher](https://discourse.gohugo.io/u/gleicher)\
**Post date:** [May 22, 2025, 2:58pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/4 "2025-05-22T14:58:42Z")

</div>

@irkode

Thank you!

That’s magic! I was able to get a (miniature) test with defer to work.

Just curious… why did you suggest step 1?  
In my test, I did it by hacking the existing “single page” template - replacing the existing `{{ .Content }}` with:

```auto
        {{- if .Params.defer }}
                {{- $ctx := dict "page" . }}
                {{- with (templates.Defer (dict "data" $ctx)) }}
                    {{ .page.Content }}
                    {{warnf "defer: %s" .page.Title}}
                {{- end }}
            {{- else}}
			{{ .Content }}
            {{ warnf "no defer: %s" .Title }}
            {{- end}}

```

Is there some unintended consequence of this that I am going to discover?

(I did this before the later reply)

---

<div class="post-metadata">

**Author:** ![gleicher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/gleicher/32/11543_2.png) [@gleicher](https://discourse.gohugo.io/u/gleicher)\
**Post date:** [May 22, 2025, 3:02pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/5 "2025-05-22T15:02:39Z")

</div>

Thank you.

Yes, that code is very similar to what I want to do. The first use case is very short snippets of text (so keeping them as strings in a map seems OK).

I was still thinking about the basic version (creating a checklist of all the things over the pages). Links back might be a nice thing in the future.

For now, I think “optimal” is “easiest” - which is pretty short term thinking. (yes, there is a lot of technical debt).

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [May 22, 2025, 3:04pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/6 "2025-05-22T15:04:31Z")

</div>

Actually, optimal is easiest. Give me a few minutes to dig up a similar, perhaps identical, use case from the past.

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [May 22, 2025, 3:33pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/7 "2025-05-22T15:33:02Z")

</div>

Try this:

```plaintext
git clone --single-branch -b hugo-forum-topic-54816 https://github.com/jmooring/hugo-testing hugo-forum-topic-54816
cd hugo-forum-topic-54816
hugo server

```

Files of interest:

- layouts/\_shortcodes/capture.html
- layouts/snippets/section.html

The “capture” shortcode uses the page store to hold an array of all snippets captured on the page. Each element in the array is a map which holds an anchor `id` and the shortcode context.

The “snippets” template ranges over all pages on this site, forces rendering of each one so that the page stores are updated, then lists the snippets with a link to where they were captured. I like this approach because you can easily filter and sort the snippet listing.

---

<div class="post-metadata">

**Author:** ![gleicher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/gleicher/32/11543_2.png) [@gleicher](https://discourse.gohugo.io/u/gleicher)\
**Post date:** [May 22, 2025, 3:59pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/8 "2025-05-22T15:59:37Z")

</div>

Thank you!  
I really appreciate your generousity with your time and knowledge.

There is a lot for me to learn from this! I get the basic idea (loop over the pages and look into their individual stores). I will need to read it carefully and think about how this applies. (and a ton of other lessons I am taking from it).

Some quick questions… (good answers lead to better questions)

1. why the underscore shortcodes “layout/\_shortcodes” and not “layout/shortcodes”?
2. how does the section snippet know not to force itself to render (and cause a loop)?
3. do the pages have their front matter before they are rendered (so, for example, could I wrap the inside of the loop with something like `{{ if .Params.collectstuff }}`` (so I could manually enable which pages this happens on).

And a bunch of why this and not that…

1. If I understand correctly, the “layout/snippets/section.html” page is a specialized layout that applies to the “\_index.md” page of the snippets section. could this have been a shortcode that was put on some random page in the middle?
2. Is there some best practice to make sure that this specialized section.html page tracks changes to the “generic” used by default? (or in this case just in layouts)
3. How would this compare with the defer strategy? It seems less magical (although, the force rendering trick is pretty magical too).

Again, thanks for your generosity. This is really amazingly helpful.

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [May 22, 2025, 4:05pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/9 "2025-05-22T16:05:14Z")

</div>

> [@gleicher](#):
>
> layout/\_shortcodes

New template system in v0.146.0 and later. See [notes](https://gohugo.io/templates/new-templatesystem-overview/).

> [@gleicher](#):
>
> could I wrap the inside of the loop with something like

Yes, but perform a `debug.Timer` A/B test. I think you’ll find that looking for the existence of a page store is plenty fast, and might be faster than another conditional. I tested `HasShortcode` and was surprised at the performance difference.

> [@gleicher](#):
>
> section snippet know not to force itself to render

I don’t understand the question.

> [@gleicher](#):
>
> could this have been a shortcode that was put on some random page

Yes.

> [@gleicher](#):
>
> tracks changes to the “generic” used by default

I don’t understand the question.

> [@gleicher](#):
>
> compare with the defer strategy

It’s easier for me to reason about.

---

<div class="post-metadata">

**Author:** ![irkode](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/irkode/32/26135_2.png) [@irkode](https://discourse.gohugo.io/u/irkode)\
**Post date:** [May 22, 2025, 4:05pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/10 "2025-05-22T16:05:47Z")

</div>

always a hundred ways to die 😉 I like @jmooring approach

> [@gleicher](#):
>
> why did you suggest step 1?

to answer the question:

I consider that page something special , I would also have expected it’s rather a list page than a normal page in the middle of all the others.  
using a dedicated template

- shows clearly that this is special
- avoids deadlocks if you don’t set the params correctly when adding a new page
- makes each template clearer  
no condition to evaluate 100 times for one hit

---

<div class="post-metadata">

**Author:** ![gleicher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/gleicher/32/11543_2.png) [@gleicher](https://discourse.gohugo.io/u/gleicher)\
**Post date:** [May 22, 2025, 4:07pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/11 "2025-05-22T16:07:51Z")

</div>

All good reasons! Thank you!

---

<div class="post-metadata">

**Author:** ![gleicher](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/gleicher/32/11543_2.png) [@gleicher](https://discourse.gohugo.io/u/gleicher)\
**Post date:** [May 22, 2025, 4:08pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/12 "2025-05-22T16:08:17Z")

</div>

Thank you!

I need to go off and do some learning…

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [May 22, 2025, 4:14pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/13 "2025-05-22T16:14:55Z")

</div>

One more note about performance. For the test site I added 2000 pages that don’t call the “capture” shortcode. There’s wasn’t a material difference in build time, meaning that looping over every page in the site didn’t make a lot of difference when compared to just looping over those _with_ page stores.

For a site with a few hundred pages I wouldn’t bother with the A/B testing, unless you have some really nasty shortcodes that do ~~stupid~~ questionable things.

---

<div class="post-metadata">

**Author:** ![jmooring](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.gohugo.io/jmooring/32/4214_2.png) [@jmooring](https://discourse.gohugo.io/u/jmooring)\
**Post date:** [May 22, 2025, 4:46pm UTC](https://discourse.gohugo.io/t/collecting-values-over-a-site-using-site-store/54816/14 "2025-05-22T16:46:14Z")

</div>

Disregard my performance notes above. My test was unrealistic. It is _significantly_ faster to test for `HasShortcode` _before_ you force content rendering, for example:

```plaintext
  {{ range site.Pages }} {{/* filter and sort as needed */}}
    {{ if .HasShortcode "capture" }}
      {{ $noop := .WordCount }} {{/* force content rendering */}}
      {{ with .Store.Get "things" }}
        <ul>
          {{ range . }}
            <li>
              {{ .ctx.Inner | .ctx.Page.RenderString }}
              <a href="{{ .ctx.Page.RelPermalink }}#{{ .anchor }}">(go to source)</a>
            </li>
          {{ end }}
        </ul>
      {{ end }}
    {{ end }}
  {{ end }}

```

I’ve updated the test repository.
