Cookie Consent by Free Privacy Policy Generator 📌 Build an AI-powered campaign manager (Next.js, OpenAI, CopilotKit)


✅ Build an AI-powered campaign manager (Next.js, OpenAI, CopilotKit)


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

TL;DR

In this article, you'll learn how to build an AI-powered campaign manager application that allows you to create and analyze advertisement campaigns, enabling you to make the right decisions for your business.

We'll cover how to:

  • build web applications with Next.js,
  • integrate AI assistants into software applications with CopilotKit, and
  • create action-specific AI copilots that handle various tasks within the application.
  • Build a campaign manager

Image description

CopilotKit: The framework for building in-app AI copilots

CopilotKit is an open-source AI copilot platform. We make it easy to integrate powerful AI into your React apps.

Build:

  • ChatBot: Context-aware in-app chatbots that can take actions in-app 💬
  • CopilotTextArea: AI-powered textFields with context-aware autocomplete & insertions 📝
  • Co-Agents: In-app AI agents that can interact with your app & users 🤖

https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3us3vc140aun0dvrdof.gif

Star CopilotKit ⭐️

Prerequisites

To fully understand this tutorial, you need to have a basic understanding of React or Next.js.

We'll also make use of the following:

  • Radix UI - for creating accessible UI components for the application.
  • OpenAI API Key - to enable us to perform various tasks using the GPT models.
  • CopilotKit - an open-source copilot framework for building custom AI chatbots, in-app AI agents, and text areas.

Project Set up and Package Installation

First, create a Next.js application by running the code snippet below in your terminal:

npx create-next-app campaign-manager

Select your preferred configuration settings. For this tutorial, we'll be using TypeScript and Next.js App Router.

Next.js App Installation

Next, install HeroiconsRadix UI, and its primitive components into the project.

npm install @heroicons/react @radix-ui/react-avatar @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-icons @radix-ui/react-label @radix-ui/react-popover @radix-ui/react-select @radix-ui/react-slot @radix-ui/react-tabs

Also, install the Recharts library - a React library for creating interactive charts - and the following utility packages:

npm install recharts class-variance-authority clsx cmdk date-fns lodash react-day-picker tailwind-merge tailwindcss-animate

Finally, install the CopilotKit packages. These packages enable the AI copilot to retrieve data from the React state and make decisions within the application.

npm install @copilotkit/react-ui @copilotkit/react-textarea @copilotkit/react-core @copilotkit/backend

Congratulations! You're now ready to build the application.

Building the Campaign Manager App with Next.js

In this section, I'll walk you through building the user interface for the campaign manager application.

First, let’s do some initial set up.

Create a components and lib folder within the src folder.

cd src
mkdir components lib

Within the lib folder, we'll declare the static types and default campaigns for the application. Therefore, create data.ts and types.ts files within the lib folder.

cd lib
touch data.ts type.ts

Copy the code snippet below into the type.ts file. It declares the campaign attributes and their data types.

export interface Campaign {
    id: string;
    objective?:
        | "brand-awareness"
        | "lead-generation"
        | "sales-conversion"
        | "website-traffic"
        | "engagement";
    title: string;
    keywords: string;
    url: string;
    headline: string;
    description: string;
    budget: number;
    bidStrategy?: "manual-cpc" | "cpa" | "cpm";
    bidAmount?: number;
    segment?: string;
}

Create the default campaign lists for the application and copy them into the data.ts file.

import { Campaign } from "./types";

export let DEFAULT_CAMPAIGNS: Campaign[] = [
    {
        id: "1",
        title: "CopilotKit",
        url: "https://www.copilotkit.ai",
        headline: "Copilot Kit - The Open-Source Copilot Framework",
        description:
            "Build, deploy, and operate fully custom AI Copilots. In-app AI chatbots, AI agents, AI Textareas and more.",
        budget: 10000,
        keywords: "AI, chatbot, open-source, copilot, framework",
    },
    {
        id: "2",
        title: "EcoHome Essentials",
        url: "https://www.ecohomeessentials.com",
        headline: "Sustainable Living Made Easy",
        description:
            "Discover our eco-friendly products that make sustainable living effortless. Shop now for green alternatives!",
        budget: 7500,
        keywords: "eco-friendly, sustainable, green products, home essentials",
    },
    {
        id: "3",
        title: "TechGear Solutions",
        url: "https://www.techgearsolutions.com",
        headline: "Innovative Tech for the Modern World",
        description:
            "Find the latest gadgets and tech solutions. Upgrade your life with smart technology today!",
        budget: 12000,
        keywords: "tech, gadgets, innovative, modern, electronics",
    },
    {
        id: "4",
        title: "Global Travels",
        url: "https://www.globaltravels.com",
        headline: "Travel the World with Confidence",
        description:
            "Experience bespoke travel packages tailored to your dreams. Luxury, adventure, relaxation—your journey starts here.",
        budget: 20000,
        keywords: "travel, luxury, adventure, tours, global",
    },
    {
        id: "5",
        title: "FreshFit Meals",
        url: "https://www.freshfitmeals.com",
        headline: "Healthy Eating, Simplified",
        description:
            "Nutritious, delicious meals delivered to your door. Eating well has never been easier or tastier.",
        budget: 5000,
        keywords: "healthy, meals, nutrition, delivery, fit",
    },
];

Since we are using Radix UI to create base UI components that can be easily customized with TailwindCSS, create a utils.ts file within the lib folder and copy the following code snippet into the file.

//👉🏻 The lib folder now contains 3 files - data.ts, type.ts, util.ts
//👇🏻 Copy the code below into the "lib/util.ts" file.
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
    return twMerge(clsx(inputs));
}

export function randomId() {
    return Math.random().toString(36).substring(2, 15);
}

Navigate into the components folder and create three other folders within it.

cd components
mkdir app dashboard ui

The components/app folder will contain various components to be used within the application, while the dashboard folder contains the UI components for some elements.

The ui folder holds multiple UI elements created using Radix UI. Copy these elements within the project repository into the folder.

Congratulations! The ui folder should contain the necessary UI elements. Now, we can use them to create the various components needed within the application.

Creating the application UI components

Here, I'll walk you through creating the user interface for the application.

Application User Interface

First, navigate to the app/page.tsx file and paste the following code snippet into it. This file renders an App component declared within the components/app folder.

"use client";
import { App } from "@/components/app/App";

export default function DashboardPage() {
    return <App />;
}

Create the App.tsx, CampaignForm.tsx, MainNav.tsx, and UserNav.tsx files within the components/app folder.

cd components/app
touch App.tsx CampaignForm.tsx MainNav.tsx UserNav.tsx

Copy the code snippet below into the App.tsx file.

"use client";
import { DEFAULT_CAMPAIGNS } from "@/lib/data";
import { Campaign } from "@/lib/types";
import { randomId } from "@/lib/utils";
import { Dashboard } from "../dashboard/Dashboard";
import { CampaignForm } from "./CampaignForm";
import { useState } from "react";
import _ from "lodash";

export function App() {
    //👇🏻 default segments
    const [segments, setSegments] = useState<string[]>([
        "Millennials/Female/Urban",
        "Parents/30s/Suburbs",
        "Seniors/Female/Rural",
        "Professionals/40s/Midwest",
        "Gamers/Male",
    ]);

    const [campaigns, setCampaigns] = useState<Campaign[]>(
        _.cloneDeep(DEFAULT_CAMPAIGNS)
    );

    //👇🏻 updates campaign list
    function saveCampaign(campaign: Campaign) {
        //👇🏻 newly created campaign
        if (campaign.id === "") {
            campaign.id = randomId();
            setCampaigns([campaign, ...campaigns]);
        } else {
            //👇🏻 existing campaign - search for the campaign and updates the campaign list
            const index = campaigns.findIndex((c) => c.id === campaign.id);
            if (index === -1) {
                setCampaigns([...campaigns, campaign]);
            } else {
                campaigns[index] = campaign;
                setCampaigns([...campaigns]);
            }
        }
    }

    const [currentCampaign, setCurrentCampaign] = useState<Campaign | undefined>(
        undefined
    );

    return (
        <div className='relative'>
            <CampaignForm
                segments={segments}
                currentCampaign={currentCampaign}
                setCurrentCampaign={setCurrentCampaign}
                saveCampaign={(campaign) => {
                    if (campaign) {
                        saveCampaign(campaign);
                    }
                    setCurrentCampaign(undefined);
                }}
            />
            <Dashboard
                campaigns={campaigns}
                setCurrentCampaign={setCurrentCampaign}
                segments={segments}
                setSegments={setSegments}
            />
        </div>
    );
}
  • From the code snippet above,
    • I created a list of default segments for the campaign and made a deep copy of the already defined campaign list.
    • The saveCampaign function accepts a campaign as a parameter. If the campaign does not have an ID, it means it is newly created, so it adds it to the campaign list. Otherwise, it finds the campaign and updates its attributes.
    • The Dashboard and the CampaignForm components accept the segments and the campaigns as props.

The Dashboard component displays various UI elements on the dashboard, while the CampaignForm component enables users to create and save a new campaign in the application.

You can also update the dashboard and app components using the code snippets from the GitHub repository.

Congratulations! You should have a working web application that allows users to view and create new campaigns.

In the upcoming section, you'll learn how to add CopilotKit to the application to analyze and make decisions based on the goals and budget of each campaign.

Application Overview

Analyzing ad campaigns with AI using CopilotKit

Here, you'll learn how to add AI to the application to help you analyze your campaigns and make the best decisions.

Before we proceed, visit the OpenAI Developers' Platform and create a new secret key.

Fetch OpenAI API key

Create a .env.local file and copy the your newly created secret key into the file.

OPENAI_API_KEY=<YOUR_OPENAI_SECRET_KEY>
OPENAI_MODEL=gpt-4-1106-preview

Next, you need to create an API endpoint for CopilotKit. Within the Next.js app folder, create an api/copilotkit folder containing a route.ts file.

cd app
mkdir api && cd api
mkdir copilotkit && cd copilotkit
touch route.ts

Copy the code snippet below into the route.ts file. The CopilotKit backend accept users’ requests and make decisions using the OpenAI model.

import { CopilotBackend, OpenAIAdapter } from "@copilotkit/backend";

export const runtime = "edge";

export async function POST(req: Request): Promise<Response> {
    const copilotKit = new CopilotBackend({});
    const openaiModel = process.env["OPENAI_MODEL"];

    return copilotKit.response(req, new OpenAIAdapter({ model: openaiModel }));
}

To connect your application to this API endpoint, update the app/page.tsx file as shown below:

"use client";
import { App } from "@/components/app/App";
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";

export default function DashboardPage() {
    return (
        <CopilotKit url='/api/copilotkit/'>
            <CopilotSidebar
                instructions='Help the user create and manage ad campaigns.'
                defaultOpen={true}
                labels={{
                    title: "Campaign Manager Copilot",
                    initial:
                        "Hello there! I can help you manage your ad campaigns. What campaign would you like to work on?",
                }}
                clickOutsideToClose={false}
            >
                <App />
            </CopilotSidebar>
        </CopilotKit>
    );
}

The CopilotKit component wraps the entire application and accepts a url prop that contains a link to the API endpoint. The CopilotSidebar component adds a chatbot sidebar panel to the application, enabling us to provide various instructions to CopilotKit.

Adding CopilotKit to Next.js

How to enable the AI copilot to perform various actions

CopilotKit provides two hooks that enable us to handle user's request and plug into the application state: useCopilotAction and useMakeCopilotReadable.

The useCopilotAction hook allows you to define actions to be carried out by CopilotKit. It accepts an object containing the following parameters:

  • name - the action's name.
  • description - the action's description.
  • parameters - an array containing the list of the required parameters.
  • render - the default custom function or string.
  • handler - the executable function that is triggered by the action.
useCopilotAction({
    name: "sayHello",
    description: "Say hello to someone.",
    parameters: [
        {
            name: "name",
            type: "string",
            description: "name of the person to say greet",
        },
    ],
    render: "Process greeting message...",
    handler: async ({ name }) => {
        alert(`Hello, ${name}!`);
    },
});

The useMakeCopilotReadable hook provides the application state to CopilotKit.

import { useMakeCopilotReadable } from "@copilotkit/react-core";

const appState = ...;
useMakeCopilotReadable(JSON.stringify(appState));

CopilotKit also allows you to provide context to the user's prompt, enabling it to make adequate and precise decisions.

Add a guidance.ts and a script.ts to the lib folder within your project, and copy this guidance and script suggestions into the file to enable CopilotKit make decisions.

Within the App component, pass the current date, script suggestions, and guidance into CopilotKit.

import { GUIDELINE } from "@/lib/guideline";
import { SCRIPT_SUGGESTION } from "@/lib/script";
import {
    useCopilotAction,
    useMakeCopilotReadable,
} from "@copilotkit/react-core";

export function App() {
    //-- 👉🏻 ...other component functions

    //👇🏻 Ground the Copilot with domain-specific knowledge for this use-case: marketing campaigns.
    useMakeCopilotReadable(GUIDELINE);
    useMakeCopilotReadable(SCRIPT_SUGGESTION);

    //👇🏻 Provide the Copilot with the current date.
    useMakeCopilotReadable("Today's date is " + new Date().toDateString());

    return (
        <div className='relative'>
            <CampaignForm
                segments={segments}
                currentCampaign={currentCampaign}
                setCurrentCampaign={setCurrentCampaign}
                saveCampaign={(campaign) => {
                    if (campaign) {
                        saveCampaign(campaign);
                    }
                    setCurrentCampaign(undefined);
                }}
            />
            <Dashboard
                campaigns={campaigns}
                setCurrentCampaign={setCurrentCampaign}
                segments={segments}
                setSegments={setSegments}
            />
        </div>
    );
}

Create a CopilotKit action within the App component that creates a new campaign or edits an existing one when the user provides such instruction.

useCopilotAction({
    name: "updateCurrentCampaign",
    description:
        "Edit an existing campaign or create a new one. To update only a part of a campaign, provide the id of the campaign to edit and the new values only.",
    parameters: [
        {
            name: "id",
            description:
                "The id of the campaign to edit. If empty, a new campaign will be created",
            type: "string",
        },
        {
            name: "title",
            description: "The title of the campaign",
            type: "string",
            required: false,
        },
        {
            name: "keywords",
            description: "Search keywords for the campaign",
            type: "string",
            required: false,
        },
        {
            name: "url",
            description:
                "The URL to link the ad to. Most of the time, the user will provide this value, leave it empty unless asked by the user.",
            type: "string",
            required: false,
        },
        {
            name: "headline",
            description:
                "The headline displayed in the ad. This should be a 5-10 words",
            type: "string",
            required: false,
        },
        {
            name: "description",
            description:
                "The description displayed in the ad. This should be a short text",
            type: "string",
            required: false,
        },

        {
            name: "budget",
            description: "The budget of the campaign",
            type: "number",
            required: false,
        },
        {
            name: "objective",
            description: "The objective of the campaign",
            type: "string",
            enum: [
                "brand-awareness",
                "lead-generation",
                "sales-conversion",
                "website-traffic",
                "engagement",
            ],
        },

        {
            name: "bidStrategy",
            description: "The bid strategy of the campaign",
            type: "string",
            enum: ["manual-cpc", "cpa", "cpm"],
            required: false,
        },
        {
            name: "bidAmount",
            description: "The bid amount of the campaign",
            type: "number",
            required: false,
        },
        {
            name: "segment",
            description: "The segment of the campaign",
            type: "string",
            required: false,
            enum: segments,
        },
    ],
    handler: (campaign) => {
        const newValue = _.assign(
            _.cloneDeep(currentCampaign),
            _.omitBy(campaign, _.isUndefined)
        ) as Campaign;

        setCurrentCampaign(newValue);
    },
    render: (props) => {
        if (props.status === "complete") {
            return "Campaign updated successfully";
        } else {
            return "Updating campaign";
        }
    },
});

Add another action that simulates an API call to allow CopilotKit to retrieve historical data from previously created campaigns.

// Provide this component's Copilot with the ability to retrieve historical cost data for certain keywords.
// Will be called automatically when needed by the Copilot.
useCopilotAction({
    name: "retrieveHistoricalData",
    description: "Retrieve historical data for certain keywords",
    parameters: [
        {
            name: "keywords",
            description: "The keywords to retrieve data for",
            type: "string",
        },
        {
            name: "type",
            description: "The type of data to retrieve for the keywords.",
            type: "string",
            enum: ["CPM", "CPA", "CPC"],
        },
    ],
    handler: async ({ type }) => {
        // fake an API call that retrieves historical data for cost for certain keywords based on campaign type (CPM, CPA, CPC)
        await new Promise((resolve) => setTimeout(resolve, 2000));

        function getRandomValue(min: number, max: number) {
            return (Math.random() * (max - min) + min).toFixed(2);
        }

        if (type == "CPM") {
            return getRandomValue(0.5, 10);
        } else if (type == "CPA") {
            return getRandomValue(5, 100);
        } else if (type == "CPC") {
            return getRandomValue(0.2, 2);
        }
    },
    render: (props) => {
        // Custom in-chat component rendering. Different components can be rendered based on the status of the action.
        let label = "Retrieving historical data ...";
        if (props.args.type) {
            label = `Retrieving ${props.args.type} for keywords ...`;
        }
        if (props.status === "complete") {
            label = `Done retrieving ${props.args.type} for keywords.`;
        }

        const done = props.status === "complete";
        return (
            <div className=''>
                <div className=' w-full relative max-w-xs'>
                    <div className='absolute inset-0 h-full w-full bg-gradient-to-r from-blue-500 to-teal-500 transform scale-[0.80] bg-red-500 rounded-full blur-3xl' />
                    <div className='relative shadow-xl bg-gray-900 border border-gray-800  px-4 py-8 h-full overflow-hidden rounded-2xl flex flex-col justify-end items-start'>
                        <h1 className='font-bold text-sm text-white mb-4 relative z-50'>
                            {label}
                        </h1>
                        <p className='font-normal text-base text-teal-200 mb-2 relative z-50 whitespace-pre'>
                            {props.args.type &&
                                `Historical ${props.args.type}: ${props.result || "..."}`}
                        </p>
                    </div>
                </div>
            </div>
        );
    },
});

Application Preview

Congratulations! You've completed the project for this tutorial.

Conclusion

CopilotKit is an incredible tool that allows you to add AI Copilots to your products within minutes. Whether you're interested in AI chatbots and assistants or automating complex tasks, CopilotKit makes it easy.

If you need to build an AI product or integrate an AI tool into your software applications, you should consider CopilotKit.

You can find the source code for this tutorial on GitHub:

https://github.com/CopilotKit/campaign-manager-demo

Thank you for reading!

...

✅ Build an AI-powered campaign manager (Next.js, OpenAI, CopilotKit)


📈 38.74 Punkte

✅ How to Build: AI-powered PowerPoint App (Next.js, OpenAI & CopilotKit)


📈 38.74 Punkte

✅ Build a spreadsheet app with an AI-copilot (Next.js, gpt4, LangChain, & CopilotKit)


📈 35.71 Punkte

✅ How to build: a v0.dev clone (Next.js, GPT4 & CopilotKit)


📈 35.71 Punkte

✅ Project using CopilotKit with Next.js implementing chatbot and AutoSuggestion.


📈 30.69 Punkte

✅ Project using CopilotKit with Next.js implementing chatbot and AutoSuggestion.


📈 30.69 Punkte

✅ I created a v0.dev clone with Next.js, GPT4 & CopilotKit


📈 30.69 Punkte

✅ AI-powered Resume and Cover Letter Generator (Next.js, GPT4, Langchain & CopilotKit)


📈 30.69 Punkte

✅ Build an AI-Powered Resume & Cover Letter Generator (CopilotKit, LangChain, Tavily & Next.js)


📈 30.69 Punkte

✅ How to Build an AI-powered To-Do list (Next.js, GPT4, & CopilotKit)


📈 30.69 Punkte

✅ AI-Powered Frontend UI Components Generator (Next.js, GPT4, Langchain, & CopilotKit)


📈 30.69 Punkte

✅ Build An AI-Powered Code Generator (Nextjs, CopilotKit, gemini-pro, Langchain)


📈 24.89 Punkte

✅ Integrate Copilot feature into your React applications using CopilotKit


📈 24.89 Punkte

✅ 🖋️ Unlock Your Writing Potential with CopilotKit's AI-Powered Wizardry!


📈 24.89 Punkte

✅ Meet CopilotKit: An Open-Source Copilot Platform for Seamless AI Integration in Any Application


📈 24.89 Punkte

✅ Unlock Next-Level Authentication in Next.js with Next Auth and TypeScript Module Augmentation


📈 17.39 Punkte

✅ UseRouter import from next/navigation or next/router in App Router Next JS?


📈 17.39 Punkte

✅ Build a website with Next.js using next/images


📈 16.61 Punkte

✅ Next.js SEO for Developers – How to Build Highly Performant Apps with Next


📈 16.61 Punkte

✅ Windows Phones “Likely” to Get Next Windows 10 Mobile RS2 Build Next Week


📈 16.61 Punkte

✅ Next Windows 10 RS2 Build with Wi-Fi Bug Fix to Launch “In the Next Few Days”


📈 16.61 Punkte

✅ Windows Phones “Likely” to Get Next Windows 10 Mobile RS2 Build Next Week


📈 16.61 Punkte

✅ Next Windows 10 RS2 Build with Wi-Fi Bug Fix to Launch “In the Next Few Days”


📈 16.61 Punkte

✅ House GOP Campaign Committee Says Its Emails Were Hacked During 2018 Campaign


📈 16.41 Punkte

✅ Days Before Election: Macron Campaign Says It Is the Victim of Massive, Coordinated Hacking Campaign


📈 16.41 Punkte

✅ How To Buy OpenAI Stock 2023: Invest in ChatGPT OpenAI


📈 16.11 Punkte

✅ This is what OpenAI thinks of both Linux and Windows I took this straight form OpenAI GPT3


📈 16.11 Punkte

✅ OpenAI's Biggest Fear Is Coming True (AGI BY 2027 But NOT by OpenAI)


📈 16.11 Punkte

✅ OpenAI WHISTLEBLOWER Reveals What OpenAI Is Really Like!


📈 16.11 Punkte

✅ Apple Eyes Dual AI Deal: Google & OpenAI After OpenAI Hierarchical Turbulence


📈 16.11 Punkte

✅ OpenAI gets Reddit’s real-time access to posts for ChatGPT, Reddit gets access to OpenAI’s tech


📈 16.11 Punkte

✅ OpenAI's Leaked INTERNAL AI AGENTS,,New Custom OpenAI Models, Google Research, A.I GENERATED GAMES,


📈 16.11 Punkte











matomo

Datei nicht gefunden!