Next JS (OpenAI SDK)
Overview
Section titled “Overview”If you’re using OpenAI JS/TS SDK with completions API, use this example to send chat data from Next.js to Growl.
Examples
Section titled “Examples”Streaming Text
Section titled “Streaming Text”In this example, we use the OpenAI SDK with completions API and streaming, and forward the data to Growl within an after call.
import recordGrowlEvent from './growl'import OpenAI from "openai";
export async function POST(req: Request) { // visitor_id is required - must be obtained from window.GrowlAds.getVisitorId() on client-side const { messages, visitor_id }: { messages: any[]; visitor_id: string } = await req.json(); const client = new OpenAI();
// Ask the API to stream Server-Sent Events (SSE) const stream = await client.chat.completions.create({ model: "gpt-4o-mini", messages: messages, stream: true, });
const encoder = new TextEncoder();
const summary = { textParts: [] as string[], // collect *all* text chunks here fullText: "", };
const headersObject = Object.fromEntries(req.headers.entries());
after(async() => { summary.fullText = summary.textParts.join(""); await recordGrowlEvent({ publisher_id: "<publisher_id>", user_id: "<user-id>", user_email: "<user-email>", visitor_id: visitor_id, // from client: await GrowlAds.getVisitorId() chat_id: "<chat-id>", headers: headersObject, user_message: { text : messages[messages.length -1] }, ai_message: { text: summary.fullText } }) })
const readable = new ReadableStream({ async start(controller) { try { for await (const event of stream) { // The stream sends typed events; emit text deltas to the client if (event.choices[0].delta.content) { controller.enqueue( encoder.encode(event.choices[0].delta.content || "") ); summary.textParts.push(event.choices[0].delta.content || ""); // store the entire text } if (event.choices[0].finish_reason === "stop") { controller.close(); } } } catch (err) { controller.error(err); } }, });
return new Response(readable, { headers: { "Content-Type": "text/plain; charset=utf-8" }, });}Non-streaming Text
Section titled “Non-streaming Text”In this example, we use the after function provided by the Next.js SDK and forward the data to Growl.
import recordGrowlEvent from './growl'import OpenAI from "openai";
export async function POST(req: Request) { // visitor_id is required - must be obtained from window.GrowlAds.getVisitorId() on client-side const { messages, visitor_id }: { messages: any[]; visitor_id: string } = await req.json(); const client = new OpenAI();
try { const completion = await client.chat.completions.create({ model: "gpt-4o-mini", messages: messages, });
const fullText = completion.choices[0]?.message?.content ?? "";
const summary = { textParts: [fullText], fullText, };
after(async () => { const headersObject = Object.fromEntries(req.headers.entries());
await recordGrowlEvent({ publisher_id: "<publisher_id>", user_id: "<user-id>", user_email: "<user-email>", visitor_id: visitor_id, // from client: await GrowlAds.getVisitorId() chat_id: "<chat-id>", headers: headersObject, user_message: { text: messages[messages.length - 1] }, ai_message: { text: summary.fullText } } }) });
return new Response(fullText, { headers: { "Content-Type": "text/plain; charset=utf-8" }, }); } catch (err) { return new Response("Internal Server Error", { status: 500 }); }}