feat: opção de subir a campanha já ativa (no ar)
Antes tudo subia PAUSED por padrão. Agora o pipeline propaga um status comum para campanha, conjunto e anúncio (os 3 precisam estar ACTIVE para entregar). A rota aceita activate=true e o Preview ganha um toggle "Iniciar a campanha já ativa" (default desmarcado = pausada para revisão). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6068f77b09
commit
349203b761
3 changed files with 60 additions and 17 deletions
|
|
@ -242,10 +242,16 @@ export async function POST(req: Request) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Por padrão sobe PAUSED (revisar antes de ativar). Quando activate=true,
|
||||||
|
// os 3 níveis (campanha/conjunto/anúncio) sobem ACTIVE e já entram em
|
||||||
|
// análise/entrega na Meta.
|
||||||
|
const finalStatus = body.activate === true ? 'ACTIVE' : 'PAUSED';
|
||||||
|
|
||||||
const result = await createFullCampaign(mcpClient, {
|
const result = await createFullCampaign(mcpClient, {
|
||||||
campaign_name,
|
campaign_name,
|
||||||
objective: finalObjective,
|
objective: finalObjective,
|
||||||
daily_budget: finalDailyBudget,
|
daily_budget: finalDailyBudget,
|
||||||
|
status: finalStatus,
|
||||||
bid_strategy: finalBidStrategy,
|
bid_strategy: finalBidStrategy,
|
||||||
bid_amount: finalBidStrategy === 'LOWEST_COST_WITHOUT_CAP' ? undefined : finalBidAmount,
|
bid_amount: finalBidStrategy === 'LOWEST_COST_WITHOUT_CAP' ? undefined : finalBidAmount,
|
||||||
targeting: {
|
targeting: {
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ export default function CreateCampaignPage() {
|
||||||
// Estampar o preço/oferta no criativo gerado por IA (bom p/ low-ticket DR).
|
// Estampar o preço/oferta no criativo gerado por IA (bom p/ low-ticket DR).
|
||||||
const [stampOffer, setStampOffer] = useState(false);
|
const [stampOffer, setStampOffer] = useState(false);
|
||||||
|
|
||||||
|
// Subir a campanha já ativa (no ar) em vez de pausada para revisão.
|
||||||
|
const [startActive, setStartActive] = useState(false);
|
||||||
|
|
||||||
const [uploadedImageBytes, setUploadedImageBytes] =
|
const [uploadedImageBytes, setUploadedImageBytes] =
|
||||||
useState<string | null>(null);
|
useState<string | null>(null);
|
||||||
|
|
||||||
|
|
@ -571,6 +574,9 @@ export default function CreateCampaignPage() {
|
||||||
cta:
|
cta:
|
||||||
copyVariations[selectedCopy]
|
copyVariations[selectedCopy]
|
||||||
.cta || 'LEARN_MORE',
|
.cta || 'LEARN_MORE',
|
||||||
|
|
||||||
|
// Sobe ACTIVE (no ar) ou PAUSED (revisar antes) nos 3 níveis.
|
||||||
|
activate: startActive,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -1475,7 +1481,23 @@ export default function CreateCampaignPage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-between items-center glass-card-static p-4">
|
<div className="glass-card-static p-4 flex flex-col gap-4">
|
||||||
|
<label className="flex items-start gap-2.5 cursor-pointer select-none">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={startActive}
|
||||||
|
onChange={(e) => setStartActive(e.target.checked)}
|
||||||
|
className="mt-0.5 h-4 w-4 accent-[var(--accent)]"
|
||||||
|
/>
|
||||||
|
<span className="text-xs text-white/70 leading-relaxed">
|
||||||
|
Iniciar a campanha já <strong>ativa</strong> (no ar)
|
||||||
|
<span className="block text-white/40">
|
||||||
|
Marcado: campanha, conjunto e anúncio sobem ativos e entram em análise/entrega na Meta. Desmarcado: sobem <strong>pausados</strong> pra você revisar e dar play no Gerenciador.
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setStep('config')}
|
onClick={() => setStep('config')}
|
||||||
|
|
@ -1489,10 +1511,11 @@ export default function CreateCampaignPage() {
|
||||||
className="btn-primary flex items-center gap-2 px-8 py-3"
|
className="btn-primary flex items-center gap-2 px-8 py-3"
|
||||||
>
|
>
|
||||||
<Send size={16} />
|
<Send size={16} />
|
||||||
Aprovar e Publicar na Meta
|
{startActive ? 'Publicar e Ativar na Meta' : 'Aprovar e Publicar (pausada)'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* DONE */}
|
{/* DONE */}
|
||||||
|
|
@ -1505,7 +1528,9 @@ export default function CreateCampaignPage() {
|
||||||
Campanha no Ar!
|
Campanha no Ar!
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-sm text-white/60 max-w-md mb-8">
|
<p className="text-sm text-white/60 max-w-md mb-8">
|
||||||
Seus criativos, públicos e orçamentos foram enviados com sucesso para o seu Gerenciador de Anúncios. A campanha entrará em análise pela Meta em instantes.
|
{startActive
|
||||||
|
? 'Tudo enviado para o seu Gerenciador de Anúncios. A campanha subiu ATIVA e entra em análise da Meta agora — começa a entregar assim que for aprovada.'
|
||||||
|
: 'Tudo enviado para o seu Gerenciador de Anúncios. A campanha subiu PAUSADA — revise no Gerenciador e dê play quando quiser colocar no ar.'}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-4">
|
<div className="flex gap-4">
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -585,6 +585,8 @@ export interface AddAdToAdSetParams {
|
||||||
description: string;
|
description: string;
|
||||||
cta: string;
|
cta: string;
|
||||||
ad_account_id?: string;
|
ad_account_id?: string;
|
||||||
|
// Status do ANÚNCIO criado (ACTIVE | PAUSED). Default PAUSED.
|
||||||
|
status?: string;
|
||||||
|
|
||||||
is_whatsapp?: boolean;
|
is_whatsapp?: boolean;
|
||||||
whatsapp_link?: string;
|
whatsapp_link?: string;
|
||||||
|
|
@ -739,6 +741,7 @@ export async function addAdToAdSet(client: Client, params: AddAdToAdSetParams) {
|
||||||
name: `${params.ad_name} — Ad`,
|
name: `${params.ad_name} — Ad`,
|
||||||
adset_id: params.adset_id,
|
adset_id: params.adset_id,
|
||||||
creative_id: creativeId,
|
creative_id: creativeId,
|
||||||
|
status: params.status,
|
||||||
ad_account_id: params.ad_account_id,
|
ad_account_id: params.ad_account_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -775,6 +778,9 @@ export interface FullCampaignParams {
|
||||||
description: string;
|
description: string;
|
||||||
cta: string;
|
cta: string;
|
||||||
ad_account_id?: string;
|
ad_account_id?: string;
|
||||||
|
// Status aplicado a campanha, conjunto e anúncio (ACTIVE | PAUSED).
|
||||||
|
// Default PAUSED — para um anúncio entregar, os 3 níveis precisam estar ACTIVE.
|
||||||
|
status?: string;
|
||||||
|
|
||||||
bid_strategy?: string;
|
bid_strategy?: string;
|
||||||
bid_amount?: number;
|
bid_amount?: number;
|
||||||
|
|
@ -790,10 +796,14 @@ export interface FullCampaignParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createFullCampaign(client: Client, params: FullCampaignParams) {
|
export async function createFullCampaign(client: Client, params: FullCampaignParams) {
|
||||||
|
// Status comum aos 3 níveis. Default PAUSED (revisar antes de ativar).
|
||||||
|
const status = params.status || 'PAUSED';
|
||||||
|
|
||||||
// Step 1: Campaign
|
// Step 1: Campaign
|
||||||
const campaign = await createCampaign(client, {
|
const campaign = await createCampaign(client, {
|
||||||
name: params.campaign_name,
|
name: params.campaign_name,
|
||||||
objective: params.objective,
|
objective: params.objective,
|
||||||
|
status,
|
||||||
ad_account_id: params.ad_account_id,
|
ad_account_id: params.ad_account_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -834,6 +844,7 @@ export async function createFullCampaign(client: Client, params: FullCampaignPar
|
||||||
destination_type: destinationType,
|
destination_type: destinationType,
|
||||||
bid_strategy: params.bid_strategy,
|
bid_strategy: params.bid_strategy,
|
||||||
bid_amount: params.bid_amount,
|
bid_amount: params.bid_amount,
|
||||||
|
status,
|
||||||
ad_account_id: params.ad_account_id,
|
ad_account_id: params.ad_account_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -856,6 +867,7 @@ export async function createFullCampaign(client: Client, params: FullCampaignPar
|
||||||
primary_text: params.primary_text,
|
primary_text: params.primary_text,
|
||||||
description: params.description,
|
description: params.description,
|
||||||
cta: params.cta,
|
cta: params.cta,
|
||||||
|
status,
|
||||||
ad_account_id: params.ad_account_id,
|
ad_account_id: params.ad_account_id,
|
||||||
is_whatsapp: params.is_whatsapp,
|
is_whatsapp: params.is_whatsapp,
|
||||||
whatsapp_link: params.whatsapp_link,
|
whatsapp_link: params.whatsapp_link,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue