# Make each frame (not slide) appear in the PDF bookmarks with beamer

I have written a beamer presentation and I would like all the frames to have corresponding PDF bookmarks, much like as in this other question on here: Beamer: how to make each frame appear in the PDF toc? . However, it seems that the answer given to that question makes every slide get a bookmark, so frames with \pauses which have multiple corresponding slides get duplicate bookmarks.

(My understanding is that in beamer, a frame is the logical concept defined as everything between the \begin{frame} and \end{frame} and may be represented in the output as one or more slides.)

I include a minimum illustrative example, based on the previously referenced answer, which I compile with pdflatex (and my \beamer@version=3.20):

\documentclass{beamer}

\usepackage{bookmark}
\usepackage{etoolbox}

\makeatletter
\apptocmd{\beamer@@frametitle}{\bookmark[page=\the\c@page,level=3]{#1}}%
{\message{** patching of \string\beamer@@frametitle succeeded **}}%
{\message{** patching of \string\beamer@@frametitle failed **}}%
\makeatother

\begin{document}

\begin{frame}{Title}
Hello \pause world
\end{frame}
\end{document}


Result: a PDF with one frame but two slides, and two bookmarks, one for each slide. Wanted: a PDF with one frame but two slides, and one bookmark, one for each frame.

I am surprised that the example doesn't work, as I would have thought that \frametitle (or rather its \@dblarg helper \beamer@@frametitle) would get called once per frame instead of (as it appears given the result) once per slide. (Is there any implementation documentation for beamer that might help me with this, as so far I've failed to find it?)

Also, as my presentation is already written, I would like to avoid having to replace \begin{frame} with \begin{myframe} everywhere if possible (especially as some of my frames use the \frametitle{Title} syntax and others the \begin{frame}{Title} syntax of setting the frame title), and I'm aware that there will be a few difficulties in this approach.

• To answer the part about why this didn't do what I expected, it seems beamer processes the frame body multiple times when there are pauses and/or overlays, and \frametitle is part of the frame body (using either syntax). – cyberSingularity Aug 10 '12 at 7:51
• Note to users: the answer to the original question has been extended with an extra patch for handling cases with mode specifications better. – cyberSingularity Oct 5 '13 at 11:50

\makeatletter
\apptocmd{\beamer@@frametitle}{\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}}%
{\message{** patching of \string\beamer@@frametitle succeeded **}}%
{\message{** patching of \string\beamer@@frametitle failed **}}%
\makeatother


adds the bookmark just for the first slide in each frame (or at least it seems to work on your MWE)

• That does indeed work, thanks, and is (embarrassingly) much simpler than anything I was going to think of. This has also led me to the idea of having one bookmark per slide, but with the 'slide in frame' number part of the bookmark caption: replacing the \apptocmd line with \apptocmd{\beamer@@frametitle}{\bookmark[page=\the\c@page,level=3]{#1 (\the\beamer@slideinframe)}}% achieves that. Hope this helps someone else too. (And it seems I can put off learning more about beamer's implementation a little longer...) – cyberSingularity Aug 10 '12 at 7:51
• why if I put these lines of code into a .sty file it does not work? – Aurelius Mar 21 '14 at 17:39

I am so happy to find this and the related thread. This is my final working solution. And I take no credit for this. I am just posting hear for some rookie Latex user like me to figure out easier:

  \AtBeginSection{\frame{\tableofcontents[currentsection]}}

\usepackage{bookmark}
\usepackage{etoolbox}
\makeatletter
% save the current definition of \beamer@@frametitle
\let\nobookmarkbeamer@@frametitle\beamer@@frametitle
% then patch it to do the bookmarks and/or TOC entries
% \apptocmd{\beamer@@frametitle}{%
\apptocmd{\beamer@@frametitle}{%
\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}
}%
{\message{** patching of \string\beamer@@frametitle succeeded **}}%
{\message{** patching of \string\beamer@@frametitle failed **}}%

\pretocmd{\beamer@checknoslide}{%
% ensure the bookmark is not created if the slide is filtered out
\let\beamer@@frametitle\nobookmarkbeamer@@frametitle
}%
{\message{** patching of \string\beamer@checknoslide succeeded **}}%
{\errmessage{** patching of \string\beamer@checknoslide failed **}}%

\makeatother


And for those who use markdown pandoc:

header-includes: |
{=latex}
% add bookmark level 2 for PDF
% from https://tex.stackexchange.com/questions/17230/beamer-how-to-make-each-frame-appear-in-the-pdf-toc

\AtBeginSection{\frame{\tableofcontents[currentsection]}}

\usepackage{bookmark}
\usepackage{etoolbox}
\makeatletter
% save the current definition of \beamer@@frametitle
\let\nobookmarkbeamer@@frametitle\beamer@@frametitle
% then patch it to do the bookmarks and/or TOC entries
% \apptocmd{\beamer@@frametitle}{%
\apptocmd{\beamer@@frametitle}{%
\only<1>{\bookmark[page=\the\c@page,level=3]{#1}}
}%
{\message{** patching of \string\beamer@@frametitle succeeded **}}%
{\message{** patching of \string\beamer@@frametitle failed **}}%

\pretocmd{\beamer@checknoslide}{%
% ensure the bookmark is not created if the slide is filtered out
\let\beamer@@frametitle\nobookmarkbeamer@@frametitle
}%
{\message{** patching of \string\beamer@checknoslide succeeded **}}%
{\errmessage{** patching of \string\beamer@checknoslide failed **}}%

\makeatother