import { getSetting } from "./settings"; const NEXTDOOR_API_URL = "https://ads.nextdoor.com/v1"; async function getNextdoorConfig() { const token = await getSetting("NEXTDOOR_API_TOKEN"); const advertiserId = await getSetting("NEXTDOOR_ADVERTISER_ID"); return { token, advertiserId }; } async function nextdoorFetch(query: string, variables: Record = {}) { const { token } = await getNextdoorConfig(); const res = await fetch(`${NEXTDOOR_API_URL}/graphql`, { method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, body: JSON.stringify({ query, variables }), }); if (!res.ok) { const text = await res.text(); throw new Error(`Nextdoor API error ${res.status}: ${text}`); } const data = await res.json(); if (data.errors?.length) { throw new Error(`Nextdoor GraphQL error: ${data.errors[0].message}`); } return data.data; } export async function createNextdoorCampaign( name: string, budget: number, schedule: { startDate: string; endDate: string } ) { const mutation = ` mutation CreateCampaign($input: CreateCampaignInput!) { createCampaign(input: $input) { campaign { id name status } } } `; return nextdoorFetch(mutation, { input: { advertiserId: (await getNextdoorConfig()).advertiserId, name, objective: "WEBSITE_CONVERSION", budget: { amount: budget, currency: "USD" }, schedule, }, }); } export async function createNextdoorAdGroup( campaignId: string, targeting: Record ) { const mutation = ` mutation CreateAdGroup($input: CreateAdGroupInput!) { createAdGroup(input: $input) { adGroup { id name status } } } `; return nextdoorFetch(mutation, { input: { campaignId, name: "Auto-generated Ad Group", targeting, }, }); } export async function uploadNextdoorCreative(imageUrl: string) { const mutation = ` mutation CreateCreative($input: CreateCreativeInput!) { createCreative(input: $input) { creative { id status } } } `; return nextdoorFetch(mutation, { input: { advertiserId: (await getNextdoorConfig()).advertiserId, imageUrl, type: "IMAGE", }, }); } export async function createNextdoorAd( adGroupId: string, creativeId: string, copy: { headline: string; body: string; ctaText: string; destinationUrl: string } ) { const mutation = ` mutation CreateAd($input: CreateAdInput!) { createAd(input: $input) { ad { id name status } } } `; return nextdoorFetch(mutation, { input: { adGroupId, creativeId, headline: copy.headline, body: copy.body, callToAction: copy.ctaText, destinationUrl: copy.destinationUrl, }, }); }