Custom JavaScript for contact timeline widget not loading after HubL template update

We recently updated our contact timeline template in Design Manager and now our custom JavaScript isn’t loading properly. The script was working fine before the template migration. We’re using HubL to inject the script and it’s supposed to enhance the timeline widget with custom event visibility filters.

The script tag is present in the DOM but the event handlers aren’t attaching. Here’s what we’re loading:

<script>
  document.addEventListener('DOMContentLoaded', function() {
    const timeline = document.querySelector('.hs-timeline-widget');
    timeline.addEventListener('click', customFilterHandler);
  });
</script>

The timeline widget loads but our custom filters don’t work. Anyone experienced similar issues with HubL script management after template updates?

Had the exact same problem after migrating templates. Here’s the working solution that addresses all three aspects: timeline widget customization, proper HubL script management, and DOM event handling.

First, regarding timeline widget customization: The hs-2021 version loads the contact timeline asynchronously after initial page render. Your DOMContentLoaded approach fails because the widget doesn’t exist yet when your event listener tries to attach.

For HubL script management: Move your script to the footer using {% require_js %} in your template. This ensures proper load order:

{% require_js %}
<script>
(function() {
  function initTimeline() {
    const timeline = document.querySelector('.hs-timeline-widget');
    if (timeline) {
      timeline.addEventListener('click', customFilterHandler);
    }
  }

  if (window.hsTimeline) {
    initTimeline();
  } else {
    window.addEventListener('hs-timeline-ready', initTimeline);
  }
})();
</script>
{% end_require_js %}

For DOM event handling: Use MutationObserver as fallback if HubSpot events aren’t available:

const observer = new MutationObserver((mutations) => {
  const timeline = document.querySelector('.hs-timeline-widget');
  if (timeline) {
    initTimeline();
    observer.disconnect();
  }
});
observer.observe(document.body, { childList: true, subtree: true });

This approach handles three scenarios: widget already loaded, widget loading via HubSpot event, or widget loading asynchronously without events. The observer disconnects once the widget is found to prevent performance issues. Test this in Design Manager preview mode first before publishing.

Also verify your HubL script placement in the template. If it’s in the header, the timeline widget definitely won’t exist yet. Move it to the footer or use defer attribute. We had similar event visibility problems until we ensured proper script execution order relative to the widget initialization.

I’ve seen this before. The timeline widget in hs-2021 loads asynchronously, so DOMContentLoaded fires before the widget actually renders. Your script executes but the .hs-timeline-widget element doesn’t exist yet. Try using MutationObserver to watch for the widget insertion instead of relying on the initial page load event.