Capturing email and sending to Shopify in Headless store

Topic summary

A developer is struggling to capture email addresses in a headless Shopify store built with ReactJS for integration with Klaviyo, since Shopify Forms don’t support headless setups.

Proposed Solution:

A community member provided a detailed implementation using Klaviyo’s API directly:

  • Backend Integration: Use Klaviyo’s Subscribe API (v2) with a POST request to https://a.klaviyo.com/api/v2/list/{LIST_ID}/subscribe
  • Frontend Component: Create a React form component that captures email input and sends it to a backend endpoint
  • Server-Side Handler: Implement an API route (e.g., Next.js API route) that securely handles the Klaviyo API call using a private API key
  • Optional Enhancement: The solution supports additional customer properties like first name, last name, and phone number

Key Technical Details:

  • Code snippets provided for both React frontend and Next.js backend implementation
  • Emphasizes keeping API keys secure on the server-side
  • Uses standard fetch API for HTTP requests

The discussion remains open, awaiting confirmation from the original poster on whether the solution works.

Summarized with AI on October 29. AI used: claude-sonnet-4-5-20250929.

I have been struggling to capture email with ReactJs and send it to shopify so that we can use Klavio. In liquid based theme we can use Shopify Forms but Shopify forms does not supports Headless.

Does any one have implemented Klavio with Headless?Would appreciate any help here.

Hi @muke5hy ,

here is the way to capture email in a React (Headless Shopify) frontend and send it to Klaviyo, since Shopify Forms don’t work with headless setups.

Step by Step Solution:

1. Use Klaviyo’s API to subscribe email
Since you can’t use Shopify Forms directly, you can directly integrate with Klaviyo using their API.

➤ Klaviyo Subscribe API (v2)
You can use the Klaviyo Lists API to add emails to a list.

API Endpoint:
POST https://a.klaviyo.com/api/v2/list/{LIST_ID}/subscribe

Headers:
{
“Content-Type”: “application/json”
}

Payload:
{
“api_key”: “YOUR_PRIVATE_API_KEY”,
“profiles”: [
{
“email”: “email@example.com
}
]
}

Use private API key (server-side) or public key (client-side) depending on how secure you want it.

2. In your React frontend (client-side or server-side)
Here’s a basic React example using fetch to call a backend endpoint:

import { useState } from ‘react’;

const NewsletterSignup = () => {
const [email, setEmail] = useState(‘’);

const handleSubmit = async (e) => {
e.preventDefault();

const response = await fetch(‘/api/subscribe’, {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify({ email }),
});

const data = await response.json();
if (data.success) {
alert(‘Thanks for subscribing!’);
} else {
alert(‘There was an error.’);
}
};

return (

setEmail(e.target.value)} placeholder="Enter your email" /> Subscribe ); };

3. Your /api/subscribe endpoint (Node/Express example)

// server.js or /api/subscribe.js (in Next.js)
import fetch from ‘node-fetch’;

export default async function handler(req, res) {
const { email } = req.body;

const response = await fetch([https://a.klaviyo.com/api/v2/list/YOUR_LIST_ID/subscribe](https://a.klaviyo.com/api/v2/list/YOUR_LIST_ID/subscribe), {
method: ‘POST’,
headers: { ‘Content-Type’: ‘application/json’ },
body: JSON.stringify({
api_key: ‘YOUR_KLAVIYO_PRIVATE_API_KEY’,
profiles: [{ email }],
}),
});

if (response.ok) {
res.status(200).json({ success: true });
} else {
const error = await response.text();
res.status(500).json({ success: false, error });
}
}

Optional Step: Add Custom Properties
You can also pass other fields like name, phone, etc., if needed:

{
“profiles”: [
{
“email”: “email@example.com”,
“first_name”: “John”,
“last_name”: “Doe”
}
]
}

Please confirm if this code works, or let me know if you need guidance to implement this.

Regards,