Hugo YouTube Playlist 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 }}
The changes I made from the built-in YouTube shortcode are:
- Replaced
$srcvalue:- from:
printf "https://%s/embed/%s" $host $id - to:
printf "https://%s/embed/videoseries" $host.
- from:
- Added the
listparameter 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:
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!