Solved

Implement Embed Klaviyo forms in SPA apps like GatsbyJS / ReactJS.

  • 23 February 2021
  • 21 replies
  • 5003 views

Userlevel 1
Badge +2

Hi there, 

I am embedding klaviyo forms in our GatsbyJs project, you can also say ReactJS, as it doesn’t actually refresh the page while navigating between pages, the forms are not getting initialized, as the JS doesn’t go to find for embed code and implement because I believe that the forms are only initialized on DOMContentLoaded event and I didn’t find any trigger to pass formId/ListId and companyId which initializes the form. So, do I have any option to trigger the initialization or I have to do this weird thing called refresh/reload page.

icon

Best answer by cbarley 24 February 2021, 17:15

View original

21 replies

hey @cbarley and others,

Just chiming in here to also request that the integration be made friendly to SPAs and react in general. We use NextJs but it doesn’t seem super relevant in this case.

 

It is not currently possible for our clients to use the forms they design in klaviyo on our frontend with reliability, nor is it really scalable to ask them to reimplement all forms by creating a duplicate and then submitting it via the API. That method is fine for simple tasks like an email list signup, but becomes really cumbersome and frustrating for more complicated forms, especially when klaviyo provides such good tools for creating those forms in the first place.

Something I have seen from other integrations is making a function that reinitializes the widget script available through the window object. That way, our app can handle listening for route changes. If window.Klaviyo was created on the initial load (something that is already being done), we can just call the function as our app requires it from window.klaviyo.reinitFunction()

thanks for your help, we hope to see this soon!

Just chiming in here with a request for the Klaviyo library to expose the function that renders the form in place of the div with the correct ID! Given how many stores build their front end with React/Vue/Angular to package into Phonegap or Ionic to make a native app it’s really a pretty important feature, IMO.

Userlevel 1
Badge +2

Hey @karan.tipl, This is a great question. I have also made some React apps and hoped to use Klaviyo embed forms (nothing with Gatsby, but the same general ideas apply).

The short answer is that our forms don’t play nicely with Single Page Applications that use browser-side routing.

The long answer is that after testing any way to get this to work (creating a custom hook to call the Klaviyo.js tracking code, or the forms code that we add to a page with a Klaviyo form on it), it isn’t possible to programmatically refresh the form at this time. The product team is aware of this issue, though, I just don’t have a timeframe available for you on a fix for that.

If you’re using something like react-router, since we don’t re-fire the klaviyo.js script on those page changes, and you can’t programmatically force that without doing a hard-refresh, a Klaviyo embed form might not be the best solution for you.

We do have the ability to redirect existing sign up forms to Klaviyo from the frontend, so in your case, using a custom form and passing those submissions to Klaviyo is your best bet. We also have a server-side version of our Lists API, so if you had the ability to pass the data to your server, then call our Lists V2 API to subscribe somebody to that list, that would also work!

 

 

@cbarley

 

This shouldn’t be the accepted answer as to call the List APIs I have to call the APIs through Javascript Fetch, Axios or it’s own node-klaviyo npm package, but all of these throw CORS errors as these APIs should be built into another API in backend and for same the backend would be mandatory to maintain just to use Klaviyo APIs. So, the front-end ReactJS developer will never be able to implement Klaviyo forms anyway, not by embedding nor by invoking APIs with Form request data. It seems to be that Klaviyo is totally useless for the SPA apps directly. Let me tell you that, API request also leads one to implement location detector too, to pass the Location and timezone details with form submission and while Klaviyo embed forms do itself.

Badge +1

Also chiming in that a JS API to dynamically refresh/fetch embedded signup forms would be extremely useful for our customers that have React-based stores.

Userlevel 3
Badge +5

Hey @karan.tipl, This is a great question. I have also made some React apps and hoped to use Klaviyo embed forms (nothing with Gatsby, but the same general ideas apply).

The short answer is that our forms don’t play nicely with Single Page Applications that use browser-side routing.

The long answer is that after testing any way to get this to work (creating a custom hook to call the Klaviyo.js tracking code, or the forms code that we add to a page with a Klaviyo form on it), it isn’t possible to programmatically refresh the form at this time. The product team is aware of this issue, though, I just don’t have a timeframe available for you on a fix for that.

If you’re using something like react-router, since we don’t re-fire the klaviyo.js script on those page changes, and you can’t programmatically force that without doing a hard-refresh, a Klaviyo embed form might not be the best solution for you.

We do have the ability to redirect existing sign up forms to Klaviyo from the frontend, so in your case, using a custom form and passing those submissions to Klaviyo is your best bet. We also have a server-side version of our Lists API, so if you had the ability to pass the data to your server, then call our Lists V2 API to subscribe somebody to that list, that would also work!

 

Userlevel 1
Badge +2

Hi team @ Klaviyo,

Any updates on the roadmap of this feature. We’re using this in a React SPA also.

Userlevel 7
Badge +36

Hi everyone!

 

There aren’t any new updates yet, but I can assure you that the Product Request has been made including all of your feedback, and the team is considering the next best action carefully.

 

@jasonnuttech while there aren’t any plans for open-sourcing the JS SDK, that is an interesting idea - I will definitely reach out to see if there is any possibility of this in the future.

 

Best,

- Brian

Badge +1

That’s right, the form can still be submitted! However, the form doesn’t appear on the page at all if the specific Klaviyo embed HTML is not present in the DOM when the Klaviyo script is loaded, which is the case for many single page apps, so I don’t think the ability to submit the form matters when the form itself doesn’t render. Definitely looking forward to seeing this API become available in Klaviyo JS, let me know if I can do anything to help test or anything!

Userlevel 3
Badge +5

Hi @karan.tipl thanks for the reply. Yes you’re right, the V2 Lists API from Klaviyo’s API docs page will throw CORS errors on the frontend if you try them from the browser. That said, from the article I linked above there’s mention of an AJAX endpoint that you can use, or you can add the Lists specific form action URL to the action html attribute on the form element. Linking that here. 

The ideal solution would be of course for our forms to have an API that can refresh the form when the page changes on the frontend with React, which I’ve given to our product team as feedback. In the interim you can submit the form through that AJAX endpoint mentioned in the article I linked above and it should work properly regardless of if the page is an SPA or not. As for the IP location information, the Klaviyo tracking code should still pick that information up if the person who fills out the form becomes known to the Klaviyo cookie on your site. For your implementation, I’d recommend onSubmit making a call to our Javascript API’s identify method to cookie the user, e.g.

_learnq.push([“identify”, {

    “$email”: email from form goes here

}])

then calling the forms AJAX endpoint right after. This way you don’t lose any of the benefits of our forms and the location data our cookie can provide. 

Badge +1

Chiming in to say that Im also developing a SPA and would like to use Klaviyo forms but cant at the moment because of this issue.

Badge +1

Also chiming in to say this is very needed asap

Hi,

Our e-commerce platform utilizes Backbone and we're encountering the same issue. It's surprising that Klaviyo doesn't support SPA in 2023. Is there a projected date for a fix to this problem?"

Thanks!

Badge

@cbarely - has anything changed on this?

 

We have a React Ionic hybrid mobile app with Klaviyo installed.  We don’t have any tracking issues (that we are aware of - and the data is similair to what we get from GA, Facebook, etc.) but we have issues with Klaviyo Forms working properly (especially when bundled inside of iOS / Android - we can’t get anything to fire).

Badge

Any chance that the JS SDK for embedding could be open-sourced, so that the community could make the necessary changes? 

Badge

I had the same problem, but I used nextjs

Badge +1

Chiming in on this too...and with all due respect, the ideal solution should not be an API call, using AJAX, or anything similar. The ideal solution is Klaviyo becoming compatible with Single Page Applications! I use an SPA too and Klaviyo’s value is severely degraded on that platform. 

Hi,

We’re experiencing the same issue in our next.js / react setup. 
The sign-up forms will only load on hard page refreshes, but not when using client side routing.

I’ve seen the suggested solution from @blinkdev in many other integrations, which works great.
A great example can be found in the documentation of Trustpilot.

Userlevel 7
Badge +60

Hi @noahsark769 and @nvassalo

 

Thank you so much for you input on this feature request! We need users like you to help us know what is a priority for our users and what you want to see! There will be an update to the thread when we have news for you on this front. 

 

In the meantime, I would like to remind you that you can submit the form through that AJAX endpoint mentioned in the article linked above and it should work properly regardless of if the page is an SPA or not! 

 

Best,

Taylor 

I made a very ugly workaround for nextjs. But it works… 🙃😃

The idea is to display the form on a page through an iframe (😂) which will reload every time, even on client side navigation.
Since the iframe doesnt know its containing page’s height, we try setting it using an interval.

1. Create a client side component (for nextjs app dir)

'use client'

import React from 'react'
import { useWindowSize } from 'react-use'

export function KlaviyoForm({ id }: { id: string }) {
const ref = React.useRef<HTMLIFrameElement>(null)
const [height, setHeight] = React.useState(0)
const window = useWindowSize()

const onLoad = () => {
let lastH = 0
let tries = 0
const maxTries = 42 // try for 420ms then give up
const interval = setInterval(() => {
tries++
if (maxTries < tries) {
clearInterval(interval)
console.warn('Could not initate iframe height for klaviyo form.')
}
const h = ref.current!.contentWindow?.document.documentElement.scrollHeight || 0
if (h > 100 && h > lastH) {
clearInterval(interval)
lastH = h
setHeight(h)
}
}, 10)
}

React.useEffect(() => {
if (window) {
setHeight(ref.current!.contentWindow?.document.documentElement.scrollHeight || 0)
}
}, [window])

// onLoad on iframe doesnt work
React.useEffect(() => {
onLoad()
}, [])

return (
<>
<iframe
src={'/klaviyo-form?id=' + id}
ref={ref}
height={height + 'px'}
className="w-full"
id="iframe"
scrolling="no"
/>
{height < 100 && <div className={`bg-gray-200 animate-pulse h-96 rounded`}></div>}
</>
)
}

 

2. Create a page to display the form. Dont miss to set YOUR_ID

import Script from 'next/script'
import React from 'react'

export default async function page({ searchParams }: { searchParams: { id: string } }) {
if (!searchParams.id) return <p>Missing form id</p>

return (
<>
<Script
src="//static.klaviyo.com/onsite/js/klaviyo.js?company_id=YOUR_ID"
strategy="afterInteractive"
id={'klaviyo'}
/>
<div className={'py-6 klaviyo-form-' + searchParams.id}></div>
</>
)
}


3. Use like this on a page

import { KlaviyoForm } from '@/components/KlaviyoForm'
import React from 'react'

export default async function Salja() {
return (
<main>
<KlaviyoForm id="YOUR_FORM_ID" />
</main>
)
}

 

Badge +1

Just had contact with support, they don’t have any idea if this is on the roadmap or not. Neither do they now what priority this has on their side.

The Klaviyo embedded forms are completely useless when you are on a react based website.

Also pinging in that we have this issue. More and more stores are going PWA. But it seems like this is not a priority at Klaviyo at all, since it has been pointed out for years. 

Reply