Can you *set* page variables, etc. in go templates, etc

I see the ability to create new local variables and Scratch variables, but what I was hoping to do was check to see if a page level Param variable existed, and if not go ahead and create it one of my theme templates before calling an internal template which uses that variable.

More specifically, I was hoping to check to see if a post’s disqus_url was set, and build a new default if not.

So that’s the initial question, and if answered, I’ll know more than I do now and that’ll come in handy even though I expect my actual scenario for wanting to do this in this particular case is, well, dumb.

I fully expect one answer to be something to the effect of, “Um, why would you do this?”

The answer to that mostly is because I’m new to Hugo and don’t know any better, and that there’s a huge mess of not understood junk cluttering what the real solution to the original problem is. On the off chance that someone actually wants to tackle any of that, here’s the situation.

I am messing around with Hugo and making a new site, which I’m looking at locally with Hugo server, and wish to be able to view internal to my lan by various readers across various devices. After that, I’m pushing it to gitlab and using their typical pages CI workflow to deploy it there. I’m also looking at netlify and have it set up to deploy there on a push to gitlab. Yeah, probably excessive but one of the main reasons for any of this was trying out different generators, workflows, hosts, services, etc.

So, based on the above, I have some deploys with the baseURL being relative, some with it being a subdir on a host (gitlab/github project pages for example), some with it being at the root of the host (gitlab/github user/org pages, netlify, etc.).

I figured I’d just keep baseURL in the config.toml file set to “/”, then override it as needed on the command line in the build/deploy step. I found I needed to set the baseURL to the full base, with host, in any actual deployment where I wanted disqus to work, because otherwise it would try to embed with the relative url for the disqus_url (which isn’t cool, according to disqus, https://help.disqus.com/customer/en/portal/articles/472098-javascript-configuration-variables )
As an aside, I don’t really understand the differences between the universal code they provide and the code generated in template_embedded.go, in terms of the config function vs. the differently named/set vars.

So, since relative URLS weren’t cool for the disqus url, and since I noticed in the implementation code (bad user!) that if the param disqus_url was set, that would be used rather than the permalink, I thought I’d kill 2 birds with 1 stone, and thought I’d make a new site level config called DisqusBaseURL, and then combine that with the relative version of the permalink to get a single name to use. I’m not sure that’s really something I want to do or that will even work as expected, since I thought the disqus_identifier was actually what was used to look up and, ahem, identify, the threads. But I still wanted to give it a shot.

First I naively (given, this is all kind of that…) tried to put something like
disqus_url={{with .Site.DisqussBaseURL}}{{ . }}/{{ .Permalink }}{{ end }}
In my default.md archetype file’s front matter. I guess I was at first thinking that when I did a
hugo new post/whatever.md
That it would at that stage process the template stuff and leave me with a disqus_url all set. That’s kind of dumb upon reflection, but I’ll admit to it anyway. Next I put quotes around the template stuff thinking that it would be stuck in the generated default front matter as a string (and it was), then might be processed when Hugo actually did the site generation (It wasn’t). I tried a shortcode version too, but I guess nothing is ever processed from frontmatter like that.

So, then I figured I’d just go ahead and set the disqus_url in the template, right before the call to the internal disqus template. I figured I’d check to see if it had already been set, and only if it was not, and only if .Site.DisqussBaseURL was set, then I’d combine them and assign it to disqus_url. … and here we are - I discovered I didn’t see any way to actually set the variable at that point.

Not sure if this is what you are after, but let me give you an idea of how I’m working with Disqus on my playground/dev site that I think will make it easy for you to manage.

  1. My config.toml. One thing to keep in mind moving forward is that you can add whatever params you want to your config and then access them by calling something like .Site.Params.MyDisqusShortname; that is, rather than your current pattern of .Site.MyDisqusShortname.
    Here is what’s in my current config file:
UseDisqus = true
disqusShortname = "yourdisqusshortname"
  1. I then have the following in the front matter of my posts:
removecomments:

Which can be set to true if I want to remove the comments from a particular page.

  1. Then in the layout for my posts, I make a call to a partial similar to the following:
<!--layouts/partials/disqus_comments_partial.html-->
{{if and .Site.Params.UseDisqus (not .Params.removecomments) }}
<div id="disqus_thread"></div>
<script>
if (window.location.hostname == "localhost") {
  console.log("Local dev, so no Disqus comments.");
} else {
  var disqus_config = function() {
    this.page.url = PAGE_URL;
    this.page.identifier = PAGE_IDENTIFIER;
  };
  (function() {
    var d = document,
      s = d.createElement('script');
    s.src = '//{{.Site.Params.disqusShortname}}.disqus.com/embed.js';
    s.setAttribute('data-timestamp', +new Date());
    (d.head || d.body).appendChild(s);
  })();
}
</script>
{{end}}

Notice that I’ve modified the script a little bit so that it doesn’t run during local development (I do the same for my netlify dev site and for Google Analytics).

The reason I set a site-wide variable and a page-level variable is that the former let’s me turn off all commenting at once if I ever wanted to and the page-level gives me that much more granular control.

Also, creating variables in Hugo is slightly different than what you’re used to, I think. For example, your disqus_url=... from above is off in a few ways:

  1. Assign variables within the dynamic double curlies: eg -
    {{$disqusUrl := .Site.Params.disqusUrl}}
    
  2. Front matter is serialized data, not a place for templating logic. The templating logic should happen at the templating layer. If you’re looking for default values, in the template you can call something like {{.Site.Params.DisqusUrl | default .Permalink}}, although, again, I’m not sure what you’re trying to do with the examples you gave.

Hope that helps…

Thanks. I like the point about site wide discussion on/off in addition to per page. In my wall of text, there are really multiple questions, that just kind of hint at the tip of the iceberg, so I appreciate your willingness to jump in on any of them - thank you.

My variable assignment was front matter, as part of my explaining initial thought process. As I noted, and you pointed out, I discovered that was incomplete and wishful thinking on my part. I wonder if thinking you can put short codes, or anything to be processed, in front matter entries is common among newbies? I didn’t see any in my face statements that it was purely static.

I had been trying to use the internal discus template. If I instead do as you did I see how I could accomplish what I’d set out to do (whether or not what I was trying is a good idea is another issue of course).

The default value example you give at the end is similar to what is done inside the internal template. But, since I was trying to use it vs. recreate it, that meant I needed to change the page param disqus_url myself, in order for the internal template to see it and use it instead of the permalink. If as you did I put in the disqus code myself, I can do what I was looking to do. Now that I’ve looked at the internal template code and seen there’s not a lot of other stuff going on, my hesitance at doing it myself is somewhat less, and your example gives me food for thought.

That still leaves my question though of can one set a page (or site) level Param key/value or page/site variable in general, from the Go template files (or anywhere outside of config.toml and front matter)? You sample variable set was a local scope variable (right?). I got the impression I couldn’t do something like {{$.Params.disqusURL := “some appropriate value”}} wasn’t possible, but I didn’t try it.

A lot of this stuff can be confusing, but really the front matter is built on specific languages (ie, yaml, toml), which are essentially serialized data formats, which would thereby not include logic/methods/templating/shortcodes. Think of them as the “model,” so they need to be manipulated outside of themselves. The way you’re joining pieces of content together is in the templating views, not in the key-value pairs within a single .md file. If you have front-end experience, think of the front matter as JSON rather than a JavaScript object (ie, which can contain a function, map, etc).

Your example of {{$.Params.disqusURL := "some appropriate value"}} doesn’t make sense if you think in the context of what I just stated above: why would you want to redefine a global value in a single page template instead of setting conditional logic in your template to take a local variable first and then the global variable second? Keep in mind that Hugo is a static site generator, and yaml front matter is the de facto format for just about every major SSG out there, none of which, to my knowledge, include logic in the front matter because doing so would go against the grain of the YAML specification.

Does that make sense?

Yeah, it does, and that is a helpful description for grokking of the front matter

The {{$.Params.disqusURL := "some appropriate value"}} in that last reply was intended to be limited to the page variable, and the only reason to have to set it was because that was the only way to get the right value into the Internal template. In this case, I could have just reimplemented the internal template, but that doesn’t necessarily seem like the right thing to always do. Probably a rare situation though.

Long discussion, but two suggestions, have a look at:

  1. The default template func
  2. The .Params func
1 Like