Content and scroll hooks
The hooks that replace the content, scroll the page and announce that a new page is visible.
The order
content:replacecontent:scrollpage:view URL has a #hash: scroll:anchorno hash: scroll:top content:replace
The new content is swapped in. Arguments: { page }, with page.html and page.url.
The default removes is-leaving, adds is-rendering, replaces every container and updates the title. It throws if a container is missing, which makes the visit fail and the browser load the page normally.
The parsed incoming document is available as visit.to.document during this hook and the ones before it. Use before to prepare it, on to work with the new DOM:
// Change the incoming content before it is inserted
pagefold.hooks.before('content:replace', (visit) => {
visit.to.document.querySelectorAll('img').forEach((img) => (img.loading = 'lazy'))
})
// Work with the new content once it is in place
pagefold.hooks.on('content:replace', () => {
initWidgets(document)
})
To change which containers are replaced in a particular visit, change visit.containers before this hook.
content:scroll
After the swap, the scroll position is updated. The default calls scroll:anchor if the URL has a hash and scroll:top otherwise. Arguments: none. Returns whether it scrolled.
scroll:top and scroll:anchor
Arguments: { options } for scroll:top, { hash, options } for scroll:anchor. options are the scrollIntoView or scrollTo options. They return true if they scrolled.
pagefold.hooks.on('scroll:anchor', (visit, args) => {
args.options.behavior = 'smooth'
})
Visits with visit.scroll.reset = false (back and forward by default) do not scroll to the top. Set visit.scroll.target to a selector or hash to scroll somewhere else, or to false to not scroll to an anchor.
page:view
The new page is on screen. Arguments: { url, title }. Fires once per visit, after the content is replaced and the scroll is set, before the in-animation.
This is where you send analytics page views.
pagefold.hooks.on('page:view', (visit, { url, title }) => {
analytics.page({ path: url, title })
})
url is the path and query of the new page (/about/?x=1), not a full address, so new URL(url) throws. The browser is already on the new page: read window.location.href, window.location.pathname and document.title. visit.from.url is the page that was left. document.referrer does not change between visits, so build the referrer from visit.from.url:
pagefold.hooks.on('page:view', (visit) => {
window.dataLayer.push({
event: 'VirtualPageview',
virtualPageURL: window.location.href,
virtualPageTitle: document.title,
virtualPagePath: window.location.pathname,
virtualPageReferrer: window.location.origin + visit.from.url,
})
})
The page is already on screen when page:view runs, so an error thrown by a handler is logged in the console and the visit goes on. It does not reload the page. Handlers run one after the other, and the others still run for that visit.
The Analytics plugin does all of this for you.