Embed YouTube Playlist in Hugo with Shortcode

How to embed a Youtube playlist in a Hugo site with custom Shortcode

One time, I wanted to embed my YouTube playlist (not a single video) into my Hugo site, but I found that there is no built-in shortcode for that. So I created a custom shortcode for it.

The shortcode is very simple. I just modified it from the built-in Hugo YouTube shortcode.

YouTube Playlist Shortcode for Hugo

To create the shortcode, create a new HTML file named youtube-playlist.html inside the layouts/_shortcodes directory.

Here’s the YouTube playlist shortcode. Feel free to copy it:

  1{{- /*
  2Renders an embedded YouTube playlist.
  3
  4@param {bool} [allowFullScreen=true] Whether the iframe element can activate full screen mode.
  5@param {bool} [autoplay=false] Whether to automatically play the video. Forces mute to be true.
  6@param {string} [class] The class attribute of the wrapping div element. When specified, removes the style attributes from the iframe element and its wrapping div element.
  7@param {bool} [controls=true] Whether to display the video controls.
  8@param {int} [end] The time, measured in seconds from the start of the video, when the player should stop playing the video.
  9@param {string} [id] The YouTube playlist id. Optional if the id is the first and only positional argument.
 10@param {string} [loading=eager] The loading attribute of the iframe element.
 11@param {bool} [loop=false] Whether to indefinitely repeat the video. Ignores the start and end arguments after the first play.
 12@param {bool} [mute=false] Whether to mute the video. Always true when autoplay is true.
 13@param {int} [start] The time, measured in seconds from the start of the video, when the player should start playing the video.
 14@param {string} [title] The title attribute of the iframe element. Defaults to "YouTube video".
 15
 16@returns {template.HTML}
 17
 18@reference https://developers.google.com/youtube/player_parameters
 19
 20@example {{< youtube-playlist PLy4N_3BZ1ec3jGntdLBPVBV2TSTwySvrx >}}
 21@example {{< youtube-playlist id=PLy4N_3BZ1ec3jGntdLBPVBV2TSTwySvrx loading=lazy start=30 >}}
 22*/}}
 23
 24{{- $pc := .Page.Site.Config.Privacy.YouTube }}
 25{{- $remoteErrID := "err-youtube-remote" }}
 26{{- if not $pc.Disable }}
 27  {{- with $id := or (.Get "id") (.Get 0) }}
 28
 29    {{- /* Set defaults. */}}
 30    {{- $allowFullScreen := true }}
 31    {{- $autoplay := 0 }}
 32    {{- $class := "" }}
 33    {{- $controls := 1 }}
 34    {{- $end := 0 }}
 35    {{- $loading := "eager" }}
 36    {{- $loop := 0 }}
 37    {{- $mute := 0 }}
 38    {{- $start := 0 }}
 39    {{- $title := "YouTube Playlist" }}
 40    {{- $iframeAllowList := "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" }}
 41
 42    {{- /* Get arguments. */}}
 43    {{- if in (slice "true" true 1) ($.Get "allowFullScreen") }}
 44      {{- $allowFullScreen = true }}
 45    {{- else if in (slice "false" false 0) ($.Get "allowFullScreen") }}
 46      {{- $allowFullScreen = false }}
 47    {{- end }}
 48    {{- if in (slice "true" true 1) ($.Get "autoplay") }}
 49      {{- $autoplay = 1 }}
 50    {{- else if in (slice "false" false 0) ($.Get "autoplay") }}
 51      {{- $autoplay = 0 }}
 52    {{- end }}
 53    {{- if in (slice "true" true 1) ($.Get "controls") }}
 54      {{- $controls = 1 }}
 55    {{- else if in (slice "false" false 0) ($.Get "controls") }}
 56      {{- $controls = 0 }}
 57    {{- end }}
 58    {{- if in (slice "true" true 1) ($.Get "loop") }}
 59      {{- $loop = 1 }}
 60    {{- else if in (slice "false" false 0) ($.Get "loop") }}
 61      {{- $loop = 0 }}
 62    {{- end }}
 63    {{- if or (in (slice "true" true 1) ($.Get "mute")) $autoplay }}
 64      {{- $mute = 1 }}
 65    {{- else if in (slice "false" false 0) ($.Get "mute") }}
 66      {{- $mute = 0 }}
 67    {{- end }}
 68    {{- $class := or ($.Get "class") $class }}
 69    {{- $end := or ($.Get "end") $end }}
 70    {{- $loading := or ($.Get "loading") $loading }}
 71    {{- $start := or ($.Get "start") $start }}
 72    {{- $title := or ($.Get "title") $title }}
 73
 74    {{- /* Adjust iframeAllowList. */}}
 75    {{- if $allowFullScreen }}
 76      {{- $iframeAllowList = printf "%s; fullscreen" $iframeAllowList }}
 77    {{- end }}
 78
 79    {{- /* Define src attribute. */}}
 80    {{- $host := cond $pc.PrivacyEnhanced "www.youtube-nocookie.com" "www.youtube.com" }}
 81    {{- $src := printf "https://%s/embed/videoseries" $host }}
 82    {{- $params := dict
 83      "list" $id
 84      "autoplay" $autoplay
 85      "controls" $controls
 86      "end" $end
 87      "mute" $mute
 88      "start" $start
 89      "loop" $loop
 90    }}
 91    {{- if $loop }}
 92      {{- $params = merge $params (dict "playlist" $id) }}
 93    {{- end }}
 94    {{- with querify $params }}
 95      {{- $src = printf "%s?%s" $src . }}
 96    {{- end }}
 97
 98    {{- /* Set div attributes. */}}
 99    {{- $divStyle := "position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;" }}
100    {{- if $class }}
101      {{- $divStyle = "" }}
102    {{- end }}
103
104    {{- /* Set iframe attributes. */}}
105    {{- $iframeStyle := "position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" }}
106    {{- if $class }}
107      {{- $iframeStyle = "" }}
108    {{- end }}
109    {{- $referrerpolicy := "strict-origin-when-cross-origin" }}
110
111    {{- /* Render. */ -}}
112    <div
113      {{- with $class }} class="{{ . }}" {{- end }}
114      {{- with $divStyle }} style="{{ . | safeCSS }}" {{- end -}}
115    >
116      <iframe
117        {{- with $iframeAllowList }} allow="{{ . }}" {{- end }}
118        {{- with $loading }} loading="{{ . }}" {{- end }}
119        {{- with $referrerpolicy }} referrerpolicy="{{ . }}" {{- end }}
120        {{- with $src }} src="{{ . }}" {{- end }}
121        {{- with $iframeStyle}} style="{{ . | safeCSS }}" {{- end }}
122        {{- with $title }} title="{{ . }}" {{- end -}}
123      ></iframe>
124    </div>
125  {{- else }}
126    {{- errorf "The %q shortcode requires an id argument. See %s" .Name .Position }}
127  {{- end }}
128{{- end }}
layouts/_shortcodes/youtube-playlist.html

The changes I made from the built-in YouTube shortcode are:

  • Replaced $src value:
    • from: printf "https://%s/embed/%s" $host $id
    • to: printf "https://%s/embed/videoseries" $host.
  • Added the list parameter to $params.

Usage is simple and very similar to the built-in YouTube shortcode.

For example, if I want to embed a playlist from my YouTube channel https://www.youtube.com/playlist?list=PLy4N_3BZ1ec3jGntdLBPVBV2TSTwySvrx, the playlist ID is PLy4N_3BZ1ec3jGntdLBPVBV2TSTwySvrx.

So on my Hugo site, I would write:

{{< youtube-playlist PLy4N_3BZ1ec3jGntdLBPVBV2TSTwySvrx >}}

And here’s how it looks after it’s rendered:

Subscribe to Junian Dev YouTube channel

Conclusion

That’s it for today’s post. You can now embed your YouTube playlist on your Hugo site easily.

As usual, if you have any questions or a better method, leave a comment below. Thanks for reading, and see you next time!

References