Hey Klaviyo Team!
I recently released a large scale open-source Nuxt4 project called Nitrogen, supported by the Nuxt team. This is somewhat more minimal rebuild of Shopify Hydrogen with all core storefront API features, but in a Nuxt4 environment. I am integrating Klaviyo into this template and have everything set up very well, with successful responses in my “Create Client Subscription” and “Create Back In Stock Subscription” requests. However, the issue is that I receive the correct email notification for my Client Subscription (newsletter) response, but I don't get any emails for the Back in Stock Subscription response (even when I manually update the product variant quantity in the Shopify admin to make it “back in stock”). Perhaps I need to update some setting on my Klaviyo admin side of things? Not sure…
Essentially I have it like this:
1. My /server/api/klaviyo.ts
API proxy:
/**
* Handles requests to the Klaviyo API through an API proxy.
* @param event - The H3 event containing the request data
* @returns The response from the Klaviyo API
* @see https://developers.klaviyo.com/en/reference/api_overview
*/
export default defineEventHandler(async (event) => {
const { klaviyo: options } = useRuntimeConfig();
const body = await readBody(event);
const type = body.data.type;
let endpoint = '';
switch (type) {
case 'subscription':
endpoint = `https://a.klaviyo.com/client/subscriptions/?company_id=${options.publicApiKey}`;
break;
case 'back-in-stock-subscription':
endpoint = `https://a.klaviyo.com/client/back-in-stock-subscriptions/?company_id=${options.publicApiKey}`;
break;
default:
throw createError({
statusCode: 400,
statusMessage: 'Invalid type specified.'
});
}
return await $fetch(endpoint, {
method: 'POST',
headers: {
accept: 'application/json',
revision: options.apiVersion,
'content-type': 'application/json',
Authorization: `Klaviyo-API-Key ${options.privateApiKey}`
},
body: JSON.stringify(body)
});
});
2. My use-klaviyo.ts
composable (same as React hooks):
export const useKlaviyo = () => {
/**
* Subscribes a user to a Klaviyo email list (newsletter).
* @param email - The user's email address
* @param listId - The ID of the specified Klaviyo list
* @returns The response from the Klaviyo API
*/
const subscribe = async (email: string, listId: string) => {
try {
return await $fetch('/api/klaviyo', {
method: 'POST',
body: {
data: {
type: 'subscription',
attributes: {
profile: {
data: {
type: 'profile',
attributes: { email }
}
}
},
relationships: {
list: {
data: {
type: 'list',
id: listId
}
}
}
}
}
});
} catch (error) {
console.error(`Failed to process client subscription:`, error);
throw error;
}
};
/**
* Subscribes a user to back-in-stock notifications for a product variant.
* @param email - The user's email address
* @param variantId - The selected variant ID
* @returns The response from the Klaviyo API
*/
const subscribeToBackInStock = async (email: string, variantId: string) => {
try {
return $fetch('/api/klaviyo', {
method: 'POST',
body: {
data: {
type: 'back-in-stock-subscription',
attributes: {
channels: 'EMAIL'],
profile: {
data: {
type: 'profile',
attributes: { email }
}
}
},
relationships: {
variant: {
data: {
type: 'catalog-variant',
id: `$shopify:::$default:::${variantId}`
}
}
}
}
}
});
} catch (error) {
console.error(`Failed to process back-in-stock subscription:`, error);
throw error;
}
};
return {
subscribe,
subscribeToBackInStock
};
};
3. And finally I have a basic handler function to handle the back-in-stock query:
// State
const email = ref('');
const errorMessage = ref('');
const successMessage = ref('');
const isLoading = ref(false);
// Helpers
const { subscribeToBackInStock } = useKlaviyo();
// Klaviyo subscribe
const handleBisSubscribe = async () => {
isLoading.value = true;
errorMessage.value = '';
successMessage.value = '';
if (!isEmail(email.value)) {
errorMessage.value = 'Please enter a valid email address.';
isLoading.value = false;
return;
}
if (!props.variantId) {
errorMessage.value = 'No variant ID found.';
isLoading.value = false;
return;
}
try {
await subscribeToBackInStock(email.value, props.variantId);
successMessage.value = 'Thanks! We will notify you when this product is back in stock.';
email.value = '';
} catch (error: any) {
console.error('Failed to subscribe to back-in-stock notifications:', error);
errorMessage.value = error.message || 'An error occurred. Please try again.';
} finally {
isLoading.value = false;
}
};
I get a status 200 code every time, which is great, but its confusing on how to test if this actually sends the correct back-in-stock email when a product is back in stock. Any help or guidance would be really appreciated.