The purpose of this application is to give an example of how Klaviyo's OAuth authentication combined with the powerful public API can create a unique Klaviyo Integration.
This application is an example of a Klaviyo OAuth integration which is used for pet party planning. It uses Klaviyo and a seperate database to store all party attendees' info. This app will help you understand how to make calls with our client-side API, make calls with our server-side API, sucessfully set up OAuth with Klaviyo, and more.
- Creating new users: Each user represents one Klaviyo customer who will "install" this integration by approving it to access their Klaviyo account.
- Connecting a Klaviyo account: Go through the OAuth flow and connect an account to a Klaviyo Account.
- Creating a party: Creating a
party
object saves some simple party details to mongoDB and creates a Klaviyo list to keep attendees' info. - Party signup for attendees: A page where a call is made to the server which relays the info to Klaviyo to create a new Klaviyo profile and subscribe them to the list.
- Viewing attendees: In the app, view the customers who have subscribed to the Klaviyo list.
- A Klaviyo account: Sign up for a free Klaviyo account, or sign in to your test account if you have an existing Klaviyo account.
- Ensure needed packages are installed: Ensure you have
node
(18.18 or later) installed plus the belowTools used in this application
section for more details. - A Klaviyo Integration Create a new integration for this sample application. To get help getting started with creating an integration read started with OAuth guide
- Next.js: Next.js framework is used to serve front-end pages as well as host backend endpoints
- MongoDB: A NoSQL database used to save application inter
- Mongoose: A MongoDB ORM to connect to MongoDB
- Klaviyo Api: The Klaviyo Node SDK is used for integrating with public API easier
- ... and others. These are the most relevant ones for interacting with Klaviyo. See the package.json for the full list
This application follows the Next.js app router format for creating a file structure; read more about it here. The basics you need to know are as follows:
page.tsx
files serves React components to the route composed of the parent folder's names.route.ts
files serve API endpoints to the route composed of the parent folder's name.
This application is for sample purposes only to help jump-start usage of the Klaviyo API. The JWT user authentication is a placeholder for demo purposes only and should not be implemented in a production environment.
Caution
For OAuth apps, it's highly recommended to have all API calls come from the server-side API (as opposed to using our client-side APIs which customers use for a variety or reasons) for consistency and use of OAuth specific features.
If your OAuth app does not make calls via your app's specific OAuth access token, the end user may experience unexpected behavior when using your OAuth app.
Please ensure you are signed into the correct Klaviyo account before spinning up the app.
This app starts the OAuth flow in the Klaviyo UI with the code living in the client application.
The OAuthSetup.ts
file contains the code for starting the onboarding flow.
It creates the Proof Key for Code Exchange (PKCE) codes needed for verifying the authenticity of the token creation call later and constructs the correct Klaviyo.com URL to redirect to.
To Read more about starting the OAuth flow, check out the guide in the developer portal.
Starting the OAuth flow can also be done by a server-side redirect. Additionally, the Klaviyo Node SDK provides helpers to construct the redirect url and generate PKCE codes. Check out our other OAuth sample code in Klaviyo Labs
Once the user accepts the permissions outlined in the scope
variable, Klaviyo redirects back to our application as outlined in the callback_url
parameter.
For this application, the callback routes back to the /callback
route defined in api/callback/route.ts
.
The callback route uses the Klaviyo Node SDK
to create a refresh token
and access token
.
To allow the Klaviyo Node SDK
to connect to your token storage solution (in this case, MongoDB) implement an instance of TokenStorage
.
This application defines the TokenStorage
implementation in /apis/OAuthHelpers.ts
.
To read more about how to implement your instance that connects to your preferred storage method, read the Klaviyo Node SDK
README.md
NOTE: Looking inside at TokenStorage
will show that the refresh token
is stored encrypted. DO NOT STORE THIS PLAIN TEXT; if a refresh token
is exposed, it can be exploited to create malicious access tokens
Getting the Klaviyo Public / Site ID
A common pattern for Klaviyo customers (which we discourage for partner apps) is making client-side API calls to create profiles in Klaviyo or using any other multiple client-side endpoints (which you can see in the developer portal).
Caution
For OAuth apps, it's highly recommended to have all API calls come from the server-side API (as opposed to using our client-side APIs which customers use for a variety or reasons) for consistency and use of OAuth specific features.
If your OAuth app does not make calls via your app's specific OAuth access token, the end user may experience unexpected behavior when using your OAuth app.
The Klaviyo public ID verifies which account the created profile should be under. In this application this value is retrieved to ensure that the OAuth flow was successful.
In the same file as above, right after a user's refresh
and access
tokens are created api/callback/route.ts
, the api call to the Klaviyo /accounts/
endpoint is made after creating the access_token
and refresh_token
.
This call leverages the KlaviyoOAuthSession
to connect to the implemented TokenStorage
and the AccountsApi.getAccounts
method to simplify this API call and provide a pre-created object for the response.
When the application creates a party, it also creates a Klaviyo list with the same name in the background.
The server-side endpoint to create a party is located in /api/parties/route.ts
Similar to the call above for getting the public ID, this call uses the stored OAuth token created in the OAuth flow early by creating an instance of OAuthSession
linked to the same customer identifier.
To create a list, call the ListsApi.createList
endpoint.
This API call is made from /view/parties/[id]/page.tsx
to /api/parties/[partyId]/route.ts
The server then first uses the Klaviyo Node SDK
's CreateProfile
endpoint. This adds the new attendee to the linked Klaviyo account and creates a profileId
.
The profileId
is then used to subscribe the new attendee to the list created earlier. This is done with the ProfileApi.subscribeProfiles
endpoint.
To save a custom property to the profile, in this case, pet_name
and pet_type
use the free-form object properties
attribute.
properties: {
pet_name: "Fido",
pet_type: "Dog"
}
Note: If you have double opt-in enabled for email consent, an email will be sent to the email address to confirm their subscription. For testing purposes, we recommend only inputting email addresses you have access to. See this article to learn more about email consent.
View this call in the /api/parties/[partyId]/route.ts
file.
To view the profiles in a list with OAuth, create an OAuthSession
and use the ListsApi.getListProfiles
endpoint again.
This application does use pagination, which isn't included in the sample application; fortunately, it's easy to use.
The getListProfiles
response includes a next
and prev
page value in response.body.data.links
Passing this value into .getListProfiles("listId", {pageCursor: response.body.data.links.next})
will fetch the next page of results
-
Clone this repo
-
Ensure you are using the correct node version (18.18 or later)
This can be done with:
nvm use
-
npm install
-
Copy and fill out
.env.local
cp .env.local.example .env.local
- Fill out the Client Id and Client Secret. If you don't know where to find that information, read this getting started with OAuth guide
NEXT_PUBLIC_CLIENT_ID
uses theNEXT_PUBLIC_
prefix so that the client id can be accessed from the browser - For the mongoDB url, this will depend on your preferred way to run MongoDB. The community Docker image is free, additionally, MongoDB has a free tier cloud-hosted instance called mongodb atlas
- To generate a key value to use for JWT and Encrypting
Refresh Tokens
use:node -e "const c = require('node:crypto'); console.log(c.randomBytes(32).toString('hex'))"
- To launch use
npm run dev
(defaults to localhost:3000)
- Fill out the Client Id and Client Secret. If you don't know where to find that information, read this getting started with OAuth guide