mcp-google-ads 1.4.4 → 1.6.0

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.
@@ -2,13 +2,14 @@
2
2
  * Pure builder for ad-group creation payloads. Separate from the manager so
3
3
  * it can be unit-tested without stubbing the live API.
4
4
  *
5
- * `type` for DEMAND_GEN_MULTI_ASSET_AD_GROUP emits the raw proto value 21
6
- * because the google-ads-api v23 enum map does not include it; the typed
7
- * AdGroup create path validates against the local enum, so DG creation must
8
- * flow through customer.mutateResources (which trusts the numeric value).
5
+ * DEMAND_GEN_MULTI_ASSET_AD_GROUP uses the string enum name rather than the
6
+ * integer 21. The v23 library's local enum map does not include 21, so integer
7
+ * 21 gets JSON-serialized as "UNKNOWN_ENUM_VALUE_AdGroupType_21" which the API
8
+ * rejects. Passing the string name directly bypasses the local enum lookup.
9
+ * DG creation still flows through customer.mutateResources to avoid the typed
10
+ * AdGroup.create path which only accepts known client-side enum values.
9
11
  */
10
12
  export type AdGroupTypeName = "SEARCH_STANDARD" | "DEMAND_GEN_MULTI_ASSET_AD_GROUP";
11
- export declare const AD_GROUP_TYPE_DEMAND_GEN_MULTI_ASSET = 21;
12
13
  export interface AdGroupCreateInput {
13
14
  customer_id_clean: string;
14
15
  name: string;
@@ -21,6 +22,7 @@ export interface AdGroupCreatePayload {
21
22
  campaign: string;
22
23
  status: number;
23
24
  cpc_bid_micros: number;
24
- type: number;
25
+ type: number | string;
26
+ optimized_targeting_enabled?: boolean;
25
27
  }
26
28
  export declare function buildAdGroupCreatePayload(input: AdGroupCreateInput): AdGroupCreatePayload;
@@ -1,17 +1,20 @@
1
1
  import { enums } from "google-ads-api";
2
- const AD_GROUP_TYPE_DEMAND_GEN_MULTI_ASSET = 21;
3
2
  function buildAdGroupCreatePayload(input) {
4
- const typeEnum = input.type === "DEMAND_GEN_MULTI_ASSET_AD_GROUP" ? AD_GROUP_TYPE_DEMAND_GEN_MULTI_ASSET : enums.AdGroupType.SEARCH_STANDARD;
5
- return {
3
+ const isDemandGen = input.type === "DEMAND_GEN_MULTI_ASSET_AD_GROUP";
4
+ const typeEnum = isDemandGen ? "DEMAND_GEN_MULTI_ASSET_AD_GROUP" : enums.AdGroupType.SEARCH_STANDARD;
5
+ const payload = {
6
6
  name: input.name,
7
7
  campaign: `customers/${input.customer_id_clean}/campaigns/${input.campaign_id}`,
8
8
  status: enums.AdGroupStatus.PAUSED,
9
9
  cpc_bid_micros: input.cpc_bid_micros ?? 1e6,
10
10
  type: typeEnum
11
11
  };
12
+ if (isDemandGen) {
13
+ payload.optimized_targeting_enabled = false;
14
+ }
15
+ return payload;
12
16
  }
13
17
  export {
14
- AD_GROUP_TYPE_DEMAND_GEN_MULTI_ASSET,
15
18
  buildAdGroupCreatePayload
16
19
  };
17
20
  //# sourceMappingURL=adGroupBuilder.js.map
@@ -1,5 +1,5 @@
1
1
  {
2
- "sha": "77d847b",
3
- "builtAt": "2026-04-18T18:38:13.085Z",
2
+ "sha": "7d2b185",
3
+ "builtAt": "2026-05-27T23:45:13.595Z",
4
4
  "embeddedSecrets": true
5
5
  }
@@ -17,15 +17,21 @@ function buildCampaignCreatePayload(input) {
17
17
  const campaign = {
18
18
  name: input.name,
19
19
  status: enums.CampaignStatus.PAUSED,
20
- advertising_channel_type: channelEnum
20
+ advertising_channel_type: channelEnum,
21
+ // EuPoliticalAdvertisingStatus enum: 3 = DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING.
22
+ // Required for all new campaigns in API v23+. Must be a non-zero enum value
23
+ // (proto3 strips default/zero values, so `false`/0 gets omitted and the API
24
+ // rejects with "required field not present").
25
+ contains_eu_political_advertising: enums.EuPoliticalAdvertisingStatus?.DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING ?? 3
21
26
  };
22
27
  if (channelType === "DEMAND_GEN") {
23
28
  campaign.network_settings = {
24
- target_google_search: false,
29
+ target_google_search: true,
25
30
  target_search_network: false,
26
- target_content_network: true,
31
+ target_content_network: false,
27
32
  target_partner_search_network: false
28
33
  };
34
+ campaign.audience_setting = { use_audience_grouped: true };
29
35
  }
30
36
  if (input.start_date) campaign.start_date = input.start_date;
31
37
  if (input.end_date) campaign.end_date = input.end_date;
@@ -0,0 +1,36 @@
1
+ export interface ExperimentCreateInput {
2
+ base_campaign_id: string;
3
+ name: string;
4
+ description?: string;
5
+ /** Suffix appended to the auto-created treatment campaign name. Defaults to " [EXP]" */
6
+ suffix?: string;
7
+ /** Percent of traffic sent to treatment arm (1–99). Defaults to 50. */
8
+ traffic_split_percent?: number;
9
+ start_date?: string;
10
+ end_date?: string;
11
+ }
12
+ export interface ExperimentArmPayload {
13
+ experiment: string;
14
+ name: string;
15
+ control: boolean;
16
+ traffic_split: number;
17
+ campaigns: string[];
18
+ }
19
+ export interface ExperimentPayload {
20
+ name: string;
21
+ description?: string;
22
+ suffix: string;
23
+ type: number;
24
+ status: number;
25
+ start_date?: string;
26
+ end_date?: string;
27
+ }
28
+ export declare function buildExperimentPayload(input: ExperimentCreateInput): ExperimentPayload;
29
+ export declare function buildControlArmPayload(experimentResourceName: string, baseCampaignResourceName: string, trafficSplit: number): ExperimentArmPayload;
30
+ export declare function buildTreatmentArmPayload(experimentResourceName: string, trafficSplit: number): ExperimentArmPayload;
31
+ /** Format YYYY-MM-DD from a Date (or today). */
32
+ export declare function formatDate(d?: Date): string;
33
+ /** Parse an experiment resource name and return the numeric experiment id. */
34
+ export declare function experimentIdFromResourceName(resourceName: string): string;
35
+ /** Parse a campaign resource name and return the numeric campaign id. */
36
+ export declare function campaignIdFromResourceName(resourceName: string): string;
@@ -0,0 +1,52 @@
1
+ import { enums } from "google-ads-api";
2
+ function buildExperimentPayload(input) {
3
+ return {
4
+ name: input.name,
5
+ ...input.description ? { description: input.description } : {},
6
+ suffix: input.suffix ?? " [EXP]",
7
+ type: enums.ExperimentType.SEARCH_CUSTOM,
8
+ // 7
9
+ status: enums.ExperimentStatus.SETUP,
10
+ // 6
11
+ ...input.start_date ? { start_date: input.start_date } : {},
12
+ ...input.end_date ? { end_date: input.end_date } : {}
13
+ };
14
+ }
15
+ function buildControlArmPayload(experimentResourceName, baseCampaignResourceName, trafficSplit) {
16
+ return {
17
+ experiment: experimentResourceName,
18
+ name: "Control",
19
+ control: true,
20
+ traffic_split: trafficSplit,
21
+ campaigns: [baseCampaignResourceName]
22
+ };
23
+ }
24
+ function buildTreatmentArmPayload(experimentResourceName, trafficSplit) {
25
+ return {
26
+ experiment: experimentResourceName,
27
+ name: "Treatment",
28
+ control: false,
29
+ traffic_split: trafficSplit,
30
+ campaigns: []
31
+ // Google auto-creates a copy of the base campaign
32
+ };
33
+ }
34
+ function formatDate(d) {
35
+ const dt = d ?? /* @__PURE__ */ new Date();
36
+ return dt.toISOString().slice(0, 10);
37
+ }
38
+ function experimentIdFromResourceName(resourceName) {
39
+ return resourceName.split("/").pop() ?? "";
40
+ }
41
+ function campaignIdFromResourceName(resourceName) {
42
+ return resourceName.split("/").pop() ?? "";
43
+ }
44
+ export {
45
+ buildControlArmPayload,
46
+ buildExperimentPayload,
47
+ buildTreatmentArmPayload,
48
+ campaignIdFromResourceName,
49
+ experimentIdFromResourceName,
50
+ formatDate
51
+ };
52
+ //# sourceMappingURL=experimentBuilder.js.map