mcp-meta-ads-incrementality 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-cli.js +6 -9
- package/dist/auth-cli.js.map +1 -1
- package/dist/index.js +669 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/graph.d.ts +23 -0
- package/dist/lib/graph.d.ts.map +1 -0
- package/dist/lib/graph.js +63 -0
- package/dist/lib/graph.js.map +1 -0
- package/dist/lib/naming-standards.d.ts +20 -0
- package/dist/lib/naming-standards.d.ts.map +1 -0
- package/dist/lib/naming-standards.js +60 -0
- package/dist/lib/naming-standards.js.map +1 -0
- package/dist/safe-response.d.ts +6 -0
- package/dist/safe-response.d.ts.map +1 -0
- package/dist/safe-response.js +43 -0
- package/dist/safe-response.js.map +1 -0
- package/dist/tools/audiences-and-forms.d.ts +104 -0
- package/dist/tools/audiences-and-forms.d.ts.map +1 -0
- package/dist/tools/audiences-and-forms.js +163 -0
- package/dist/tools/audiences-and-forms.js.map +1 -0
- package/dist/tools/campaign-build.d.ts +117 -0
- package/dist/tools/campaign-build.d.ts.map +1 -0
- package/dist/tools/campaign-build.js +205 -0
- package/dist/tools/campaign-build.js.map +1 -0
- package/dist/tools/lifecycle.d.ts +32 -0
- package/dist/tools/lifecycle.d.ts.map +1 -0
- package/dist/tools/lifecycle.js +43 -0
- package/dist/tools/lifecycle.js.map +1 -0
- package/dist/tools/url-tags.d.ts +145 -0
- package/dist/tools/url-tags.d.ts.map +1 -0
- package/dist/tools/url-tags.js +616 -0
- package/dist/tools/url-tags.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export interface CreateCampaignInput {
|
|
2
|
+
account_id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
objective: string;
|
|
5
|
+
status?: 'PAUSED' | 'ACTIVE';
|
|
6
|
+
special_ad_categories?: string[];
|
|
7
|
+
buying_type?: 'AUCTION' | 'RESERVED';
|
|
8
|
+
daily_budget?: number;
|
|
9
|
+
lifetime_budget?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CreateCampaignResult {
|
|
12
|
+
campaign_id: string;
|
|
13
|
+
account_id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
status: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function createCampaign(input: CreateCampaignInput, accessToken: string): Promise<CreateCampaignResult>;
|
|
18
|
+
export interface CreateAdSetInput {
|
|
19
|
+
account_id: string;
|
|
20
|
+
campaign_id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
optimization_goal: string;
|
|
23
|
+
billing_event: 'IMPRESSIONS' | 'LINK_CLICKS' | 'POST_ENGAGEMENT' | 'THRUPLAY';
|
|
24
|
+
bid_strategy?: 'LOWEST_COST_WITHOUT_CAP' | 'LOWEST_COST_WITH_BID_CAP' | 'COST_CAP';
|
|
25
|
+
bid_amount?: number;
|
|
26
|
+
targeting: Record<string, unknown>;
|
|
27
|
+
status?: 'PAUSED' | 'ACTIVE';
|
|
28
|
+
daily_budget?: number;
|
|
29
|
+
lifetime_budget?: number;
|
|
30
|
+
promoted_object?: Record<string, unknown>;
|
|
31
|
+
destination_type?: string;
|
|
32
|
+
attribution_spec?: Array<{
|
|
33
|
+
event_type: string;
|
|
34
|
+
window_days: number;
|
|
35
|
+
}>;
|
|
36
|
+
is_incremental_attribution_enabled?: boolean;
|
|
37
|
+
start_time?: string;
|
|
38
|
+
end_time?: string;
|
|
39
|
+
}
|
|
40
|
+
export interface CreateAdSetResult {
|
|
41
|
+
adset_id: string;
|
|
42
|
+
account_id: string;
|
|
43
|
+
campaign_id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
status: string;
|
|
46
|
+
}
|
|
47
|
+
export declare function createAdSet(input: CreateAdSetInput, accessToken: string): Promise<CreateAdSetResult>;
|
|
48
|
+
export interface CallToAction {
|
|
49
|
+
type: string;
|
|
50
|
+
value?: {
|
|
51
|
+
link?: string;
|
|
52
|
+
lead_gen_form_id?: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export interface CreateAdCreativeInput {
|
|
56
|
+
account_id: string;
|
|
57
|
+
name: string;
|
|
58
|
+
page_id: string;
|
|
59
|
+
image_hash?: string;
|
|
60
|
+
link: string;
|
|
61
|
+
/** Single primary text. Mutually exclusive with `messages`. */
|
|
62
|
+
message?: string;
|
|
63
|
+
/** Up to 5 primary texts (Flexible Ads / asset_feed_spec). */
|
|
64
|
+
messages?: string[];
|
|
65
|
+
/** Single headline. Mutually exclusive with `headlines`. */
|
|
66
|
+
headline?: string;
|
|
67
|
+
/** Up to 5 headlines. */
|
|
68
|
+
headlines?: string[];
|
|
69
|
+
/** Single description. Mutually exclusive with `descriptions`. */
|
|
70
|
+
description?: string;
|
|
71
|
+
/** Up to 5 descriptions. */
|
|
72
|
+
descriptions?: string[];
|
|
73
|
+
call_to_action?: CallToAction;
|
|
74
|
+
/** Shortcut: builds call_to_action={type:'SIGN_UP', value:{lead_gen_form_id}}. */
|
|
75
|
+
lead_gen_form_id?: string;
|
|
76
|
+
url_tags?: string;
|
|
77
|
+
/** Optional Instagram business account id for cross-posting. */
|
|
78
|
+
instagram_actor_id?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface CreateAdCreativeResult {
|
|
81
|
+
creative_id: string;
|
|
82
|
+
account_id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
/** Whether the creative used asset_feed_spec (multi-variant) or legacy object_story_spec. */
|
|
85
|
+
mode: 'asset_feed_spec' | 'object_story_spec';
|
|
86
|
+
}
|
|
87
|
+
export declare function createAdCreative(input: CreateAdCreativeInput, accessToken: string): Promise<CreateAdCreativeResult>;
|
|
88
|
+
export interface CreateAdInput {
|
|
89
|
+
account_id: string;
|
|
90
|
+
name: string;
|
|
91
|
+
adset_id: string;
|
|
92
|
+
creative_id: string;
|
|
93
|
+
status?: 'PAUSED' | 'ACTIVE';
|
|
94
|
+
}
|
|
95
|
+
export interface CreateAdResult {
|
|
96
|
+
ad_id: string;
|
|
97
|
+
account_id: string;
|
|
98
|
+
adset_id: string;
|
|
99
|
+
creative_id: string;
|
|
100
|
+
name: string;
|
|
101
|
+
status: string;
|
|
102
|
+
}
|
|
103
|
+
export declare function createAd(input: CreateAdInput, accessToken: string): Promise<CreateAdResult>;
|
|
104
|
+
export interface UploadImageInput {
|
|
105
|
+
account_id: string;
|
|
106
|
+
/** Base64-encoded image bytes. Prefer for tests / when caller already has bytes. */
|
|
107
|
+
image_bytes?: string;
|
|
108
|
+
/** Local file path. If provided, the file is read and base64-encoded. */
|
|
109
|
+
image_path?: string;
|
|
110
|
+
}
|
|
111
|
+
export interface UploadImageResult {
|
|
112
|
+
image_hash: string;
|
|
113
|
+
url: string;
|
|
114
|
+
account_id: string;
|
|
115
|
+
}
|
|
116
|
+
export declare function uploadImage(input: UploadImageInput, accessToken: string): Promise<UploadImageResult>;
|
|
117
|
+
//# sourceMappingURL=campaign-build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-build.d.ts","sourceRoot":"","sources":["../../src/tools/campaign-build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 1 write tools: campaign / ad set / ad creative / ad / image upload.
|
|
3
|
+
*
|
|
4
|
+
* Defaults to PAUSED status on every object so MCP callers can build a full
|
|
5
|
+
* campaign hierarchy without accidentally going live. Callers must explicitly
|
|
6
|
+
* flip status=ACTIVE (today via meta_ads_update_object_status, or directly in
|
|
7
|
+
* Ads Manager) after review.
|
|
8
|
+
*
|
|
9
|
+
* Image uploads use Meta's `bytes` form field (base64-encoded image data) —
|
|
10
|
+
* keeps everything on the standard form-urlencoded POST shape used by lib/graph.
|
|
11
|
+
*/
|
|
12
|
+
import { graphPost } from '../lib/graph.js';
|
|
13
|
+
function normalizeAccountId(accountId) {
|
|
14
|
+
return accountId.startsWith('act_') ? accountId : `act_${accountId}`;
|
|
15
|
+
}
|
|
16
|
+
export async function createCampaign(input, accessToken) {
|
|
17
|
+
const account = normalizeAccountId(input.account_id);
|
|
18
|
+
const status = input.status ?? 'PAUSED';
|
|
19
|
+
const body = {
|
|
20
|
+
name: input.name,
|
|
21
|
+
objective: input.objective,
|
|
22
|
+
status,
|
|
23
|
+
special_ad_categories: JSON.stringify(input.special_ad_categories ?? []),
|
|
24
|
+
buying_type: input.buying_type ?? 'AUCTION',
|
|
25
|
+
};
|
|
26
|
+
if (input.daily_budget !== undefined)
|
|
27
|
+
body.daily_budget = String(input.daily_budget);
|
|
28
|
+
if (input.lifetime_budget !== undefined)
|
|
29
|
+
body.lifetime_budget = String(input.lifetime_budget);
|
|
30
|
+
const res = await graphPost(`${account}/campaigns`, accessToken, body);
|
|
31
|
+
return { campaign_id: res.id, account_id: account, name: input.name, status };
|
|
32
|
+
}
|
|
33
|
+
export async function createAdSet(input, accessToken) {
|
|
34
|
+
if (input.daily_budget !== undefined && input.lifetime_budget !== undefined) {
|
|
35
|
+
throw new Error('createAdSet: pass daily_budget OR lifetime_budget, not both.');
|
|
36
|
+
}
|
|
37
|
+
if (input.daily_budget === undefined && input.lifetime_budget === undefined) {
|
|
38
|
+
throw new Error('createAdSet: budget required. Pass daily_budget or lifetime_budget, or set the budget on the parent campaign (CBO).');
|
|
39
|
+
}
|
|
40
|
+
const account = normalizeAccountId(input.account_id);
|
|
41
|
+
const status = input.status ?? 'PAUSED';
|
|
42
|
+
const body = {
|
|
43
|
+
name: input.name,
|
|
44
|
+
campaign_id: input.campaign_id,
|
|
45
|
+
optimization_goal: input.optimization_goal,
|
|
46
|
+
billing_event: input.billing_event,
|
|
47
|
+
bid_strategy: input.bid_strategy ?? 'LOWEST_COST_WITHOUT_CAP',
|
|
48
|
+
targeting: JSON.stringify(input.targeting),
|
|
49
|
+
status,
|
|
50
|
+
};
|
|
51
|
+
if (input.daily_budget !== undefined)
|
|
52
|
+
body.daily_budget = String(input.daily_budget);
|
|
53
|
+
if (input.lifetime_budget !== undefined)
|
|
54
|
+
body.lifetime_budget = String(input.lifetime_budget);
|
|
55
|
+
if (input.bid_amount !== undefined)
|
|
56
|
+
body.bid_amount = String(input.bid_amount);
|
|
57
|
+
if (input.promoted_object)
|
|
58
|
+
body.promoted_object = JSON.stringify(input.promoted_object);
|
|
59
|
+
if (input.destination_type)
|
|
60
|
+
body.destination_type = input.destination_type;
|
|
61
|
+
if (input.attribution_spec)
|
|
62
|
+
body.attribution_spec = JSON.stringify(input.attribution_spec);
|
|
63
|
+
if (input.is_incremental_attribution_enabled !== undefined) {
|
|
64
|
+
body.is_incremental_attribution_enabled = String(input.is_incremental_attribution_enabled);
|
|
65
|
+
}
|
|
66
|
+
if (input.start_time)
|
|
67
|
+
body.start_time = input.start_time;
|
|
68
|
+
if (input.end_time)
|
|
69
|
+
body.end_time = input.end_time;
|
|
70
|
+
const res = await graphPost(`${account}/adsets`, accessToken, body);
|
|
71
|
+
return {
|
|
72
|
+
adset_id: res.id,
|
|
73
|
+
account_id: account,
|
|
74
|
+
campaign_id: input.campaign_id,
|
|
75
|
+
name: input.name,
|
|
76
|
+
status,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function collectVariants(single, multi) {
|
|
80
|
+
const out = [];
|
|
81
|
+
if (multi && multi.length)
|
|
82
|
+
out.push(...multi);
|
|
83
|
+
else if (single)
|
|
84
|
+
out.push(single);
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
export async function createAdCreative(input, accessToken) {
|
|
88
|
+
const account = normalizeAccountId(input.account_id);
|
|
89
|
+
const messages = collectVariants(input.message, input.messages);
|
|
90
|
+
const headlines = collectVariants(input.headline, input.headlines);
|
|
91
|
+
const descriptions = collectVariants(input.description, input.descriptions);
|
|
92
|
+
if (messages.length === 0) {
|
|
93
|
+
throw new Error('createAdCreative: provide message or messages[].');
|
|
94
|
+
}
|
|
95
|
+
if (messages.length > 5 || headlines.length > 5 || descriptions.length > 5) {
|
|
96
|
+
throw new Error('createAdCreative: Meta caps primary texts / headlines / descriptions at 5 each.');
|
|
97
|
+
}
|
|
98
|
+
const callToAction = input.call_to_action ??
|
|
99
|
+
(input.lead_gen_form_id
|
|
100
|
+
? { type: 'SIGN_UP', value: { lead_gen_form_id: input.lead_gen_form_id } }
|
|
101
|
+
: undefined);
|
|
102
|
+
const useAssetFeedSpec = messages.length > 1 || headlines.length > 1 || descriptions.length > 1;
|
|
103
|
+
const body = { name: input.name };
|
|
104
|
+
if (input.url_tags)
|
|
105
|
+
body.url_tags = input.url_tags;
|
|
106
|
+
if (useAssetFeedSpec) {
|
|
107
|
+
// Meta "Flexible Ads" / multi-variant mode (optimization_type=DEGREES_OF_FREEDOM).
|
|
108
|
+
// Shape learned from a UI-built ad on 2026-05-14:
|
|
109
|
+
// - image_hash + CTA + link live in object_story_spec.link_data (NOT in asset_feed_spec)
|
|
110
|
+
// - asset_feed_spec contains ONLY bodies/titles/descriptions + optimization_type
|
|
111
|
+
// - No images[], link_urls, call_to_action_types, call_to_actions, ad_formats in asset_feed_spec
|
|
112
|
+
if (!input.image_hash) {
|
|
113
|
+
throw new Error('createAdCreative: asset_feed_spec (multi-variant) mode requires image_hash.');
|
|
114
|
+
}
|
|
115
|
+
const linkData = {
|
|
116
|
+
link: input.link,
|
|
117
|
+
image_hash: input.image_hash,
|
|
118
|
+
};
|
|
119
|
+
if (callToAction)
|
|
120
|
+
linkData.call_to_action = callToAction;
|
|
121
|
+
const objectStorySpec = {
|
|
122
|
+
page_id: input.page_id,
|
|
123
|
+
link_data: linkData,
|
|
124
|
+
};
|
|
125
|
+
if (input.instagram_actor_id)
|
|
126
|
+
objectStorySpec.instagram_actor_id = input.instagram_actor_id;
|
|
127
|
+
const assetFeedSpec = {
|
|
128
|
+
bodies: messages.map((text) => ({ text })),
|
|
129
|
+
optimization_type: 'DEGREES_OF_FREEDOM',
|
|
130
|
+
};
|
|
131
|
+
if (headlines.length)
|
|
132
|
+
assetFeedSpec.titles = headlines.map((text) => ({ text }));
|
|
133
|
+
if (descriptions.length)
|
|
134
|
+
assetFeedSpec.descriptions = descriptions.map((text) => ({ text }));
|
|
135
|
+
body.object_story_spec = JSON.stringify(objectStorySpec);
|
|
136
|
+
body.asset_feed_spec = JSON.stringify(assetFeedSpec);
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
const linkData = {
|
|
140
|
+
link: input.link,
|
|
141
|
+
message: messages[0],
|
|
142
|
+
};
|
|
143
|
+
if (input.image_hash)
|
|
144
|
+
linkData.image_hash = input.image_hash;
|
|
145
|
+
if (headlines.length)
|
|
146
|
+
linkData.name = headlines[0];
|
|
147
|
+
if (descriptions.length)
|
|
148
|
+
linkData.description = descriptions[0];
|
|
149
|
+
if (callToAction)
|
|
150
|
+
linkData.call_to_action = callToAction;
|
|
151
|
+
const objectStorySpec = {
|
|
152
|
+
page_id: input.page_id,
|
|
153
|
+
link_data: linkData,
|
|
154
|
+
};
|
|
155
|
+
if (input.instagram_actor_id)
|
|
156
|
+
objectStorySpec.instagram_actor_id = input.instagram_actor_id;
|
|
157
|
+
body.object_story_spec = JSON.stringify(objectStorySpec);
|
|
158
|
+
}
|
|
159
|
+
const res = await graphPost(`${account}/adcreatives`, accessToken, body);
|
|
160
|
+
return {
|
|
161
|
+
creative_id: res.id,
|
|
162
|
+
account_id: account,
|
|
163
|
+
name: input.name,
|
|
164
|
+
mode: useAssetFeedSpec ? 'asset_feed_spec' : 'object_story_spec',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export async function createAd(input, accessToken) {
|
|
168
|
+
const account = normalizeAccountId(input.account_id);
|
|
169
|
+
const status = input.status ?? 'PAUSED';
|
|
170
|
+
const body = {
|
|
171
|
+
name: input.name,
|
|
172
|
+
adset_id: input.adset_id,
|
|
173
|
+
creative: JSON.stringify({ creative_id: input.creative_id }),
|
|
174
|
+
status,
|
|
175
|
+
};
|
|
176
|
+
const res = await graphPost(`${account}/ads`, accessToken, body);
|
|
177
|
+
return {
|
|
178
|
+
ad_id: res.id,
|
|
179
|
+
account_id: account,
|
|
180
|
+
adset_id: input.adset_id,
|
|
181
|
+
creative_id: input.creative_id,
|
|
182
|
+
name: input.name,
|
|
183
|
+
status,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
export async function uploadImage(input, accessToken) {
|
|
187
|
+
let bytes = input.image_bytes;
|
|
188
|
+
if (!bytes && input.image_path) {
|
|
189
|
+
const { readFileSync } = await import('node:fs');
|
|
190
|
+
bytes = readFileSync(input.image_path).toString('base64');
|
|
191
|
+
}
|
|
192
|
+
if (!bytes) {
|
|
193
|
+
throw new Error('uploadImage: provide image_bytes (base64) or image_path.');
|
|
194
|
+
}
|
|
195
|
+
const account = normalizeAccountId(input.account_id);
|
|
196
|
+
const res = await graphPost(`${account}/adimages`, accessToken, {
|
|
197
|
+
bytes,
|
|
198
|
+
});
|
|
199
|
+
const first = res.images ? Object.values(res.images)[0] : undefined;
|
|
200
|
+
if (!first) {
|
|
201
|
+
throw new Error('uploadImage: response missing images.bytes — Graph returned no hash.');
|
|
202
|
+
}
|
|
203
|
+
return { image_hash: first.hash, url: first.url, account_id: account };
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=campaign-build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"campaign-build.js","sourceRoot":"","sources":["../../src/tools/campaign-build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type ObjectStatus = 'PAUSED' | 'ACTIVE' | 'ARCHIVED' | 'DELETED';
|
|
2
|
+
export interface UpdateObjectStatusInput {
|
|
3
|
+
object_id: string;
|
|
4
|
+
status: ObjectStatus;
|
|
5
|
+
}
|
|
6
|
+
export interface UpdateObjectStatusResult {
|
|
7
|
+
object_id: string;
|
|
8
|
+
status: ObjectStatus;
|
|
9
|
+
success: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function updateObjectStatus(input: UpdateObjectStatusInput, accessToken: string): Promise<UpdateObjectStatusResult>;
|
|
12
|
+
export interface UpdateBudgetInput {
|
|
13
|
+
object_id: string;
|
|
14
|
+
daily_budget?: number;
|
|
15
|
+
lifetime_budget?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface UpdateBudgetResult {
|
|
18
|
+
object_id: string;
|
|
19
|
+
daily_budget: number | null;
|
|
20
|
+
lifetime_budget: number | null;
|
|
21
|
+
success: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function updateBudget(input: UpdateBudgetInput, accessToken: string): Promise<UpdateBudgetResult>;
|
|
24
|
+
export interface DeleteObjectInput {
|
|
25
|
+
object_id: string;
|
|
26
|
+
}
|
|
27
|
+
export interface DeleteObjectResult {
|
|
28
|
+
object_id: string;
|
|
29
|
+
success: boolean;
|
|
30
|
+
}
|
|
31
|
+
export declare function deleteObject(input: DeleteObjectInput, accessToken: string): Promise<DeleteObjectResult>;
|
|
32
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../src/tools/lifecycle.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;AAMxE,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB;AAOD,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,uBAAuB,EAC9B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,wBAAwB,CAAC,CASnC;AAMD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAmB7B;AAMD,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,YAAY,CAChC,KAAK,EAAE,iBAAiB,EACxB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,kBAAkB,CAAC,CAG7B"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier 3 + 4 lifecycle tools: status toggle, budget update, delete.
|
|
3
|
+
*
|
|
4
|
+
* Meta uses the same POST /{id} endpoint for any object (campaign, ad set, ad)
|
|
5
|
+
* with `status` or budget fields, and DELETE /{id} for removal. This module
|
|
6
|
+
* exposes one tool per concern; callers pass an object_id of any type.
|
|
7
|
+
*/
|
|
8
|
+
import { graphDelete, graphPost } from '../lib/graph.js';
|
|
9
|
+
export async function updateObjectStatus(input, accessToken) {
|
|
10
|
+
const res = await graphPost(input.object_id, accessToken, {
|
|
11
|
+
status: input.status,
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
object_id: input.object_id,
|
|
15
|
+
status: input.status,
|
|
16
|
+
success: res.success ?? false,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export async function updateBudget(input, accessToken) {
|
|
20
|
+
if (input.daily_budget === undefined && input.lifetime_budget === undefined) {
|
|
21
|
+
throw new Error('updateBudget: pass daily_budget or lifetime_budget.');
|
|
22
|
+
}
|
|
23
|
+
if (input.daily_budget !== undefined && input.lifetime_budget !== undefined) {
|
|
24
|
+
throw new Error('updateBudget: pass daily_budget OR lifetime_budget, not both.');
|
|
25
|
+
}
|
|
26
|
+
const body = {};
|
|
27
|
+
if (input.daily_budget !== undefined)
|
|
28
|
+
body.daily_budget = String(input.daily_budget);
|
|
29
|
+
if (input.lifetime_budget !== undefined)
|
|
30
|
+
body.lifetime_budget = String(input.lifetime_budget);
|
|
31
|
+
const res = await graphPost(input.object_id, accessToken, body);
|
|
32
|
+
return {
|
|
33
|
+
object_id: input.object_id,
|
|
34
|
+
daily_budget: input.daily_budget ?? null,
|
|
35
|
+
lifetime_budget: input.lifetime_budget ?? null,
|
|
36
|
+
success: res.success ?? false,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function deleteObject(input, accessToken) {
|
|
40
|
+
const res = await graphDelete(input.object_id, accessToken);
|
|
41
|
+
return { object_id: input.object_id, success: res.success ?? false };
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../../src/tools/lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAwBzD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,KAA8B,EAC9B,WAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,SAAS,CAAuB,KAAK,CAAC,SAAS,EAAE,WAAW,EAAE;QAC9E,MAAM,EAAE,KAAK,CAAC,MAAM;KACrB,CAAC,CAAC;IACH,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,KAAK;KAC9B,CAAC;AACJ,CAAC;AAmBD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAwB,EACxB,WAAmB;IAEnB,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;QAC5E,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,IAAI,GAA2B,EAAE,CAAC;IACxC,IAAI,KAAK,CAAC,YAAY,KAAK,SAAS;QAAE,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACrF,IAAI,KAAK,CAAC,eAAe,KAAK,SAAS;QAAE,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAE9F,MAAM,GAAG,GAAG,MAAM,SAAS,CAAuB,KAAK,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACtF,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;QACxC,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,IAAI;QAC9C,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,KAAK;KAC9B,CAAC;AACJ,CAAC;AAeD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAwB,EACxB,WAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,WAAW,CAAuB,KAAK,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAClF,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,KAAK,EAAE,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export interface AdSummary {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
status: string;
|
|
5
|
+
effective_status?: string;
|
|
6
|
+
campaign_id: string;
|
|
7
|
+
creative_id: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function listAdsInCampaign(campaignId: string, accessToken: string): Promise<AdSummary[]>;
|
|
10
|
+
export interface LearningStageInfo {
|
|
11
|
+
status: string | null;
|
|
12
|
+
last_significant_edit_ts: number | null;
|
|
13
|
+
}
|
|
14
|
+
export interface AdUrlTagsInfo {
|
|
15
|
+
ad_id: string;
|
|
16
|
+
ad_name: string;
|
|
17
|
+
account_id: string;
|
|
18
|
+
campaign_id: string;
|
|
19
|
+
campaign_name: string;
|
|
20
|
+
creative_id: string;
|
|
21
|
+
object_story_id: string | null;
|
|
22
|
+
url_tags: string | null;
|
|
23
|
+
link: string | null;
|
|
24
|
+
learning_stage_info: LearningStageInfo | null;
|
|
25
|
+
}
|
|
26
|
+
export declare function getAdUrlTags(adId: string, accessToken: string): Promise<AdUrlTagsInfo>;
|
|
27
|
+
export interface UpdateAdUrlTagsResult {
|
|
28
|
+
ad_id: string;
|
|
29
|
+
ad_name: string;
|
|
30
|
+
previous_url_tags: string | null;
|
|
31
|
+
new_url_tags: string;
|
|
32
|
+
previous_creative_id: string;
|
|
33
|
+
new_creative_id: string;
|
|
34
|
+
changed: boolean;
|
|
35
|
+
learning_before: LearningStageInfo | null;
|
|
36
|
+
learning_after: LearningStageInfo | null;
|
|
37
|
+
significant_edit_triggered: boolean | null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Update url_tags via create-then-rebind WITH social-feedback preservation.
|
|
41
|
+
*
|
|
42
|
+
* The Meta UI itself forks a new creative when url_tags changes (verified by
|
|
43
|
+
* inspecting Ads Manager network calls 2026-05-05 — the internal payload
|
|
44
|
+
* shows action_metadata.type=DUPLICATION_UPGRADE and
|
|
45
|
+
* enable_social_feedback_preservation=true). Meta's relearning trigger is
|
|
46
|
+
* field-aware: changes to url_tags alone are documented as not resetting
|
|
47
|
+
* learning, when social-feedback preservation carries forward.
|
|
48
|
+
*
|
|
49
|
+
* This implementation replicates that behavior on the public Marketing API:
|
|
50
|
+
* 1. Read current creative → get object_story_id, account_id, learning_stage_info.
|
|
51
|
+
* 2. POST /act_X/adcreatives with {object_story_id, url_tags,
|
|
52
|
+
* object_story_spec.use_page_actor_override flag implicit} — same
|
|
53
|
+
* Page-post reference, only url_tags differs.
|
|
54
|
+
* 3. POST /{ad-id} with creative_id=<new>.
|
|
55
|
+
* 4. Re-read learning_stage_info; compare last_significant_edit_ts.
|
|
56
|
+
*
|
|
57
|
+
* If last_significant_edit_ts is unchanged, Meta did not consider the edit
|
|
58
|
+
* significant — confirming learning is preserved. If it advanced to roughly
|
|
59
|
+
* the time of our write, Meta did trigger a relearning event and the writer
|
|
60
|
+
* should be considered unsafe for active ads.
|
|
61
|
+
*/
|
|
62
|
+
export declare function updateAdUrlTags(adId: string, newUrlTags: string, accessToken: string, dryRun: boolean): Promise<UpdateAdUrlTagsResult>;
|
|
63
|
+
export interface SwapAdLeadFormResult {
|
|
64
|
+
ad_id: string;
|
|
65
|
+
ad_name: string;
|
|
66
|
+
previous_creative_id: string;
|
|
67
|
+
new_creative_id: string;
|
|
68
|
+
previous_form_id: string | null;
|
|
69
|
+
new_form_id: string;
|
|
70
|
+
mode: 'asset_feed_spec' | 'object_story_spec';
|
|
71
|
+
changed: boolean;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Swap the lead form on an ad by rebuilding its creative with a new form_id.
|
|
75
|
+
*
|
|
76
|
+
* Meta creatives are immutable, so we create-then-rebind:
|
|
77
|
+
* 1. Read the ad's current creative (full spec — handles both legacy
|
|
78
|
+
* object_story_spec and modern asset_feed_spec creatives).
|
|
79
|
+
* 2. POST /act_X/adcreatives with the same image/text spec but new
|
|
80
|
+
* lead_gen_form_id inside the SIGN_UP CTA.
|
|
81
|
+
* 3. POST /{ad-id} with creative_id=<new> to rebind.
|
|
82
|
+
*
|
|
83
|
+
* The ad-id is unchanged. Meta may briefly re-review.
|
|
84
|
+
*/
|
|
85
|
+
export declare function swapAdLeadForm(adId: string, newFormId: string, accessToken: string, dryRun: boolean, ctaTypeOverride?: string): Promise<SwapAdLeadFormResult>;
|
|
86
|
+
export interface RebindAdCreativeResult {
|
|
87
|
+
ad_id: string;
|
|
88
|
+
ad_name: string;
|
|
89
|
+
previous_creative_id: string;
|
|
90
|
+
new_creative_id: string;
|
|
91
|
+
changed: boolean;
|
|
92
|
+
customization_rules_preserved: boolean | null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Rebind an ad to a different creative_id. Atomic. ad_id stays stable.
|
|
96
|
+
* Use with createAdCreative to do full ad rebuilds (e.g. swap form + rebuild
|
|
97
|
+
* text content) without touching the ad_id.
|
|
98
|
+
*
|
|
99
|
+
* Safety check: if the OLD creative has `asset_customization_rules` (per-placement
|
|
100
|
+
* image rules set in Ads Manager UI) and the NEW creative does not carry them
|
|
101
|
+
* forward, the rebind is REFUSED. This catches the 2026-05-14 RDR class of bug
|
|
102
|
+
* where multi-variant headline writes silently flattened custom placements by image.
|
|
103
|
+
* Pass `force=true` to override (e.g. when the new creative deliberately replaces
|
|
104
|
+
* the placement rules).
|
|
105
|
+
*/
|
|
106
|
+
export declare function rebindAdCreative(adId: string, newCreativeId: string, accessToken: string, dryRun: boolean, force?: boolean): Promise<RebindAdCreativeResult>;
|
|
107
|
+
export interface EditCreativeTextEdits {
|
|
108
|
+
messages?: string[];
|
|
109
|
+
headlines?: string[];
|
|
110
|
+
descriptions?: string[];
|
|
111
|
+
}
|
|
112
|
+
export interface EditCreativeTextResult {
|
|
113
|
+
ad_id: string;
|
|
114
|
+
ad_name: string;
|
|
115
|
+
previous_creative_id: string;
|
|
116
|
+
new_creative_id: string;
|
|
117
|
+
mode: 'asset_feed_spec' | 'object_story_spec';
|
|
118
|
+
changed_fields: string[];
|
|
119
|
+
customization_rules_preserved: number;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Edit text fields (primary texts / headlines / descriptions) on an ad's creative
|
|
123
|
+
* while PRESERVING images, videos, asset_customization_rules (per-placement image
|
|
124
|
+
* rules set in Ads Manager UI), call_to_actions, and link_urls.
|
|
125
|
+
*
|
|
126
|
+
* For asset_feed_spec ads: replaces only the specified text arrays. Refuses the
|
|
127
|
+
* edit if the existing asset_customization_rules reference per-text labels
|
|
128
|
+
* (body_label / title_label / description_label) and the new text count differs
|
|
129
|
+
* from the old — pass force=true to override (rules may end up referencing
|
|
130
|
+
* orphaned labels and break the placement targeting).
|
|
131
|
+
*
|
|
132
|
+
* For object_story_spec (legacy single-variant) ads: replaces link_data.message
|
|
133
|
+
* (single primary text), link_data.name (single headline), link_data.description.
|
|
134
|
+
* The messages/headlines/descriptions arrays must each have length ≤ 1 in that
|
|
135
|
+
* mode.
|
|
136
|
+
*/
|
|
137
|
+
export declare function editCreativeText(adId: string, edits: EditCreativeTextEdits, accessToken: string, dryRun: boolean, force?: boolean): Promise<EditCreativeTextResult>;
|
|
138
|
+
export interface RenameAdResult {
|
|
139
|
+
ad_id: string;
|
|
140
|
+
previous_name: string;
|
|
141
|
+
new_name: string;
|
|
142
|
+
changed: boolean;
|
|
143
|
+
}
|
|
144
|
+
export declare function renameAd(adId: string, newName: string, accessToken: string, dryRun: boolean): Promise<RenameAdResult>;
|
|
145
|
+
//# sourceMappingURL=url-tags.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-tags.d.ts","sourceRoot":"","sources":["../../src/tools/url-tags.ts"],"names":[],"mappings":"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"}
|