Skip to main content
Contributor II
February 23, 2021
Solved

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

  • February 23, 2021
  • 25 replies
  • 7450 views

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.

Best answer by cbarley

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!

 

25 replies

Contributor I
September 28, 2022

@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).

Problem Solver I
January 19, 2023

Hi team @ Klaviyo,

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

jasonnuttech
Contributor I
Contributor I
February 1, 2023

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

Brian Turcotte
Klaviyo Alum
February 8, 2023

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

Contributor I
March 7, 2023

I had the same problem, but I used nextjs

Contributor I
May 9, 2023

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!

Contributor I
August 10, 2023

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.

Contributor I
October 3, 2023

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>
)
}

 

Contributor I
October 18, 2023

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!

Contributor I
February 2, 2024

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.