APIs & Integrations

Carl_
Member

Refresh/attach page forms on pages loaded by AJAX

SOLVE

Hi,

 

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.

The forms are loaded this way inline in the html.

 

<div class="textwidget">
<script charset="utf-8" type="text/javascript" src="//js.hsforms.net/forms/v2.js"></script>
<script>
hbspt.forms.create({
portalId: 000000,
formId: "xxx",
shortcode: "wp",

});
</script>
</div>

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?

0 Upvotes
1 Accepted solution
Carl_
Solution
Member

Refresh/attach page forms on pages loaded by AJAX

SOLVE
/**
* 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)
}
}

Array.from(document.querySelectorAll('.hubspot-form-el')).forEach(el => dynLoadHubSpotForms(el))

Hi @Derek_Gervais 

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.

View solution in original post

6 Replies 6
Derek_Gervais
HubSpot Alumni
HubSpot Alumni

Refresh/attach page forms on pages loaded by AJAX

SOLVE

Hey @Carl_ ,

 

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! 

0 Upvotes
Carl_
Member

Refresh/attach page forms on pages loaded by AJAX

SOLVE

Hi @Derek_Gervais thanks for your reply!

 

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

Derek_Gervais
HubSpot Alumni
HubSpot Alumni

Refresh/attach page forms on pages loaded by AJAX

SOLVE

Hey @Carl_ ,

 

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.

0 Upvotes
Carl_
Solution
Member

Refresh/attach page forms on pages loaded by AJAX

SOLVE
/**
* 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)
}
}

Array.from(document.querySelectorAll('.hubspot-form-el')).forEach(el => dynLoadHubSpotForms(el))

Hi @Derek_Gervais 

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.

MRoscoe
Member

Refresh/attach page forms on pages loaded by AJAX

SOLVE

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.

0 Upvotes
iamrobert
Member

Refresh/attach page forms on pages loaded by AJAX

SOLVE

Hi,

 

I am trying to implement this but I get the following js error:

hbspt is not defined

 

It works on initial load, but when PJAX kicks in and I go to my form page it fails.

 

<div class="hubspot-form-el">
<script charset="utf-8" src="//js.hsforms.net/forms/v2.js"></script>
<script>

hbspt.forms.create({

portalId: "zzz",

formId: "zzzz"



});

</script></div>

If I put the //js.hsforms.net/forms/v2.js script in the head it seems to work with eval.

Any Ideas?

 

 

0 Upvotes