# Injecting JavaScript from shortcode?

**URL:** <https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041>\
**Category:** Support\
**Created:** [September 29, 2021, 2:38pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041 "2021-09-29T14:38:11Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![BezPowell](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/bezpowell/32/604_2.png) [@BezPowell](https://zola.discourse.group/u/BezPowell)\
**Post date:** [September 29, 2021, 2:38pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/1 "2021-09-29T14:38:11Z")

</div>

Apologies if this has already been asked.

I was wondering whether there is a way of injecting js files from within a shortcode? I have a gallery shortcode on my site that requires some additonal js for a lightbox. The js is quite heavy, so I’d rather only load it on pages that actually have a gallery.

If possible, I’d like to be able to check whether a shortcode has been used on a page in the template, and only add the script element if the shortcode has been used at least one. The shortcode is used within markdown, rather than the template. If this worked, I could then extend the system for other components such as accordions or tabs etc.

Does anyone know of any way of achieving something like this?

Currently I have a lightweight js ‘loader’ file that uses a query selector and conditionally requires es6 modules if it finds an element with a certain class, but if possible I’d like to do away with this and just add the script element to the end of the body on pages where it is needed.

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [September 30, 2021, 10:23am UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/2 "2021-09-30T10:23:07Z")

</div>

That should already work if you mark the output in the template as `| safe`?

---

<div class="post-metadata">

**Author:** ![BezPowell](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/bezpowell/32/604_2.png) [@BezPowell](https://zola.discourse.group/u/BezPowell)\
**Post date:** [October 1, 2021, 8:07am UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/3 "2021-10-01T08:07:56Z")

</div>

Hi keats, thank you. Where would I put the script tag, and how would I check for duplication to ensure it was only loaded once?

---

<div class="post-metadata">

**Author:** ![optozorax](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/optozorax/32/587_2.png) [@optozorax](https://zola.discourse.group/u/optozorax)\
**Post date:** [October 3, 2021, 10:17pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/4 "2021-10-03T22:17:48Z")

</div>

You have [`nth` variable](https://www.getzola.org/documentation/content/shortcodes/#invocation-count) for each shortcode. You should include your JS only when this variable is equal to 1.

---

<div class="post-metadata">

**Author:** ![BezPowell](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/bezpowell/32/604_2.png) [@BezPowell](https://zola.discourse.group/u/BezPowell)\
**Post date:** [October 7, 2021, 9:39am UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/5 "2021-10-07T09:39:39Z")

</div>

I’d not seen that nth variable, thank you. I was hoping to find a way of conditionally injecting the files from the page template, so they are all at the end of the body element, but will look into using nth to inject it from the shortcode itself.

Thanks again.

---

<div class="post-metadata">

**Author:** ![Tattomoosa](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/tattomoosa/32/601_2.png) [@Tattomoosa](https://zola.discourse.group/u/Tattomoosa)\
**Post date:** [October 7, 2021, 7:16pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/6 "2021-10-07T19:16:27Z")

</div>

IMO it would be really good to add this use-case to that page on the docs.

---

<div class="post-metadata">

**Author:** ![phillord](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/phillord/32/652_2.png) [@phillord](https://zola.discourse.group/u/phillord)\
**Post date:** [December 29, 2021, 4:19pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/7 "2021-12-29T16:19:45Z")

</div>

Sorry for late post, but I am unsure how this would work. Presumably the shortcode would be add any output into it’s own location. But supporting JavaScript would go into the header or footer of the web page?

I’m curious because I would like to replicate the behaviour of the mathjax plugin for Wordpress. It uses the shortcodes in content and loads mathjax if and only if it is needed. The shortcode expands to mathjax syntax locally, but also forces the load of mathjax in the header.

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [December 30, 2021, 10:13am UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/8 "2021-12-30T10:13:17Z")

</div>

> [@phillord](#):
>
> But supporting JavaScript would go into the header or footer of the web page?

You can require a script anywhere in the page, it’s just that by default it would block the rendering of the page unless you use `defer`. I don’t know Wordpress but I don’t see how a shortcode could access `<head>`.

---

<div class="post-metadata">

**Author:** ![phillord](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/phillord/32/652_2.png) [@phillord](https://zola.discourse.group/u/phillord)\
**Post date:** [December 30, 2021, 7:54pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/9 "2021-12-30T19:54:20Z")

</div>

In wordpress the content is parsed before the header is produced. So the shortcode just sets a global variable while it is doing it’s other work. I’ve given this a go in zola, but it is not clear to me what the global context is. It doesn’t appear that variables from a shortcode are visible to other parts of the template. I don’t know if this is because of the scope or because the order in which things are evaled.

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [December 31, 2021, 10:37am UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/10 "2021-12-31T10:37:14Z")

</div>

Shortcodes are pure functions in Zola: they just get the args and render the corresponding template. You cannot set anything from a shortcode in the outer context. Do you have a link to an explanation on how it works in Wordpress that I could read?

---

<div class="post-metadata">

**Author:** ![phillord](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/phillord/32/652_2.png) [@phillord](https://zola.discourse.group/u/phillord)\
**Post date:** [December 31, 2021, 1:33pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/11 "2021-12-31T13:33:08Z")

</div>

I am not sure what explanation you are after. Wordpress shortcodes call a function. This sets a variable. The variable is then enacted later.

The equivalent in zola would be something like having a shortcode defined so:

```auto
{% set_global latex=true %}

```

and then in one of the page templates you would have something like:

```auto
{% if latex %}
latex has happened
{% else %}
latex has not happened
{% endif %}

```

Another possibility would be add some configuration to the front-matter. But as far as I can see from `__tera_context` arbitrary front matter is not available to templates. So, the only solution that I can see at the moment is to have two page templates, one with mathjax enabled and one without, which I can configure in the front-matter. That works, of course, but means multiple templates rather than conditional logic.

---

<div class="post-metadata">

**Author:** ![keats](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@keats](https://zola.discourse.group/u/keats)\
**Post date:** [December 31, 2021, 5:29pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/12 "2021-12-31T17:29:38Z")

</div>

> [@phillord](#):
>
> But as far as I can see from `__tera_context` arbitrary front matter is not available to templates.

Everything you set in the `extra` section is available.

> [@phillord](#):
>
> Wordpress shortcodes call a function. This sets a variable. The variable is then enacted later.

I see. Then it’s definitely not going to work like that. Content rendering is pretty far from the template it’s actually going to be rendered in in Zola.

---

<div class="post-metadata">

**Author:** ![phillord](https://yyz2.discourse-cdn.com/free1/user_avatar/zola.discourse.group/phillord/32/652_2.png) [@phillord](https://zola.discourse.group/u/phillord)\
**Post date:** [January 2, 2022, 12:14pm UTC](https://zola.discourse.group/t/injecting-javascript-from-shortcode/1041/13 "2022-01-02T12:14:10Z")

</div>

> [@keats](#):
>
> Everything you set in the `extra` section is available.

Ah, I had missed that! Thank you, I can use this as a solution.

> [@keats](#):
>
> I see. Then it’s definitely not going to work like that. Content rendering is pretty far from the template it’s actually going to be rendered in in Zola.

Okay. It would need a generalization of the `nth` variable I guess for this to work. Well, the `extra` front-matter is a good solution for my use case. Wordpress doesn’t have a real equivalent to front matter (although you can add metadata in the GUI) hence the use of shortcodes.
