I'm currently integrating hubspot forms on a website that uses barbajs which is a common plugin to fetch the new pages with AJAX and replaces the content inside a wrapper, thus not needing to re-fetch header and footer on each page load.
Although this breaks the scripts from finding the new page forms.
I have been checking the docs and inspecting the window.hbspt object but I haven't found any ways to make forms re-attach to the new html content. I have already found solutons for many other embedded services like youtube, vimeo with their api's. But nothing yet for HubSpot.
Does anyone have any suggestions or ideas of what I could do?
jan 15, 20207:00 AM - editado jan 15, 20207:05 AM
Membro
Refresh/attach page forms on pages loaded by AJAX
resolver
/** * Evaluate HubSpot elements containing hbspt.forms.create * @param {Element} el */ function dynLoadHubSpotForms (el) { if (el) { const widgetScript = el.querySelector('script:nth-of-type(2)') // the second script element contains the init method if (!widgetScript) return const widgetContent = widgetScript.textContent // eslint-disable-next-line no-eval eval(widgetContent) } }
This code is basically what I came up with. It works but I only use it from trusted server content, eval should never be used on any page element that can serve user generated content.
I think it would be great to have a refresh or re-eval function for hubspot js library, it would allow it to be used better together with frameworks that serve dynamic pages/SPA's with frameworks such as React or VueJS.
I'm not very familiar with Barba.js or the problem you're describing, but after doing a bit or digging I was able to find some resources that sound related to what you're working through:
It seems like you'll need to take advantage of some lifecycle events that Barba.js provides to load the forms whenever a transition is completed. I hope these are helpful!
I've looked at those issue threads at github as well. The eval thing is a possible solution although a very inefficient and very dangerous solution because I would evaulate raw HTML from the server response. What I was looking for more if the hubspot js api had some method like ".update()", ".refresh()" or anything similar for it to find any new form elements on the page. Although I guess I need to find some way to use eval in a "secure" way for this. When/if I come up with a solution I'll post it here for anyone else that might have the same problem in the future
I totally understand; at this time, there isn't a refresh functionality like you're describing. I look forward to seeing any solution you might find!
Additionally, I'd encourage you to post your idea to the HubSpot Ideas Forum. While I'm happy to pass this feedback along internally, the Ideas Forum is where the product team aggregates and monitors feedback on existing/new features like this.
jan 15, 20207:00 AM - editado jan 15, 20207:05 AM
Membro
Refresh/attach page forms on pages loaded by AJAX
resolver
/** * Evaluate HubSpot elements containing hbspt.forms.create * @param {Element} el */ function dynLoadHubSpotForms (el) { if (el) { const widgetScript = el.querySelector('script:nth-of-type(2)') // the second script element contains the init method if (!widgetScript) return const widgetContent = widgetScript.textContent // eslint-disable-next-line no-eval eval(widgetContent) } }
This code is basically what I came up with. It works but I only use it from trusted server content, eval should never be used on any page element that can serve user generated content.
I think it would be great to have a refresh or re-eval function for hubspot js library, it would allow it to be used better together with frameworks that serve dynamic pages/SPA's with frameworks such as React or VueJS.
I've had this same issue with Barba recently. My solution was a little different. Maybe it'll help someone who finds this thread.
While hubspot provides no refresh function, you can add a 'target' parameter to the embed code. The target parameter declares which element the form is appended to. This basically means that you can place the embed code in your js, rather than inline in your html. Then you can just run the js in the 'enter' barba hook, for example, to ensure the form gets created.
So my html looked like:
<!-- Pass in the portal/form IDs from the hubspot embed code as data-attributes -->
<div class="c-hbspt-form js-hs-form" data-portal-id="PORTAL_ID" data-form-id="FORM_ID"></div>
Then in my JS I had a function that checks for elements with the 'js-hs-form' class and then creates the hubspot form based on the data-attributes. The project had lots of forms, often 2/3 on a page, so the below is a solution for handling that. Could be simplified if you just have one form somewhere.
const forms = $('.js-hs-form');
if (forms.length) {
// Foreach form container, insert hubspot form
forms.each((i, item) => {
// Only add form to container if form doesn't already exist
// This was needed as I had some forms loading in outside the barba container
if (! $(item).children().length) {
$(item).attr('data-form-index', i);
portalID = $(item).data('portal-id');
formID = $(item).data('form-id');
if (portalID > '' && formID > '') {
// Here's the JS provided by the embed code
// The scripts from the embed code are moved to the footer
hbspt.forms.create({
portalId: portalID,
formId: formID,
// Target value here makes sure the form is inserted in the right place
target: `.js-hs-form[data-form-index="${i}"]`,
}
} else {
console.error('Portal ID and Form ID are required to show Hubspot Form');
}
})
}
}
Then it's just a case of running the above function on the right barba hook. You could run it on the 'enter' or 'beforeEnter' hooks, as the new DOM will then be loaded in. Using an earlier hook won't work, as you won't be able to detect any of the 'js-hs-form' containers as the next page's HTML is still unavailable.