@pipedream/google_ads 0.4.0 → 0.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.
package/README.md CHANGED
@@ -21,7 +21,7 @@ campaigns, such as campaign stats, keyword stats, and ad performance.
21
21
 
22
22
  ## Customizing API requests from within the Pipedream workflow builder
23
23
 
24
- The Pipedream components interact with Google Ads API through an interal proxy service, which protects Pipedream's developer token.
24
+ The Pipedream components interact with Google Ads API through an internal proxy service, which protects Pipedream's developer token.
25
25
 
26
26
  The component accepts a standard Google Ads API request object with the following structure:
27
27
 
@@ -7,7 +7,7 @@ export default {
7
7
  key: "google_ads-add-contact-to-list-by-email",
8
8
  name: "Add Contact to Customer List by Email",
9
9
  description: "Adds a contact to a specific customer list in Google Ads. Lists typically update in 6 to 12 hours after operation. [See the documentation](https://developers.google.com/google-ads/api/docs/remarketing/audience-segments/customer-match/get-started)",
10
- version: "0.1.6",
10
+ version: "0.1.7",
11
11
  annotations: {
12
12
  destructiveHint: true,
13
13
  openWorldHint: true,
@@ -0,0 +1,16 @@
1
+ import { adGroup } from "../../common/resources/adGroup.mjs";
2
+ import { createReportComponent } from "../../common/common-report.mjs";
3
+
4
+ export default {
5
+ ...createReportComponent(adGroup),
6
+ key: "google_ads-create-ad-group-report",
7
+ name: "Create Ad Group Report",
8
+ description: "Creates a report for the Ad Group resource. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
9
+ version: "0.0.1",
10
+ annotations: {
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ readOnlyHint: true,
14
+ },
15
+ type: "action",
16
+ };
@@ -0,0 +1,16 @@
1
+ import { ad } from "../../common/resources/ad.mjs";
2
+ import { createReportComponent } from "../../common/common-report.mjs";
3
+
4
+ export default {
5
+ ...createReportComponent(ad),
6
+ key: "google_ads-create-ad-report",
7
+ name: "Create Ad Report",
8
+ description: "Creates a report for the Ad resource. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
9
+ version: "0.0.1",
10
+ annotations: {
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ readOnlyHint: true,
14
+ },
15
+ type: "action",
16
+ };
@@ -0,0 +1,16 @@
1
+ import { campaign } from "../../common/resources/campaign.mjs";
2
+ import { createReportComponent } from "../../common/common-report.mjs";
3
+
4
+ export default {
5
+ ...createReportComponent(campaign),
6
+ key: "google_ads-create-campaign-report",
7
+ name: "Create Campaign Report",
8
+ description: "Creates a report for the Campaign resource. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
9
+ version: "0.0.1",
10
+ annotations: {
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ readOnlyHint: true,
14
+ },
15
+ type: "action",
16
+ };
@@ -15,7 +15,7 @@ export default {
15
15
  key: "google_ads-create-customer-list",
16
16
  name: "Create Customer List",
17
17
  description: "Create a new customer list in Google Ads. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/UserList)",
18
- version: "0.0.7",
18
+ version: "0.0.8",
19
19
  annotations: {
20
20
  destructiveHint: false,
21
21
  openWorldHint: true,
@@ -0,0 +1,16 @@
1
+ import { customer } from "../../common/resources/customer.mjs";
2
+ import { createReportComponent } from "../../common/common-report.mjs";
3
+
4
+ export default {
5
+ ...createReportComponent(customer),
6
+ key: "google_ads-create-customer-report",
7
+ name: "Create Customer Report",
8
+ description: "Creates a report for the Customer resource. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
9
+ version: "0.0.1",
10
+ annotations: {
11
+ destructiveHint: false,
12
+ openWorldHint: true,
13
+ readOnlyHint: true,
14
+ },
15
+ type: "action",
16
+ };
@@ -4,7 +4,7 @@ import { ad } from "../../common/resources/ad.mjs";
4
4
  import { campaign } from "../../common/resources/campaign.mjs";
5
5
  import { customer } from "../../common/resources/customer.mjs";
6
6
  import { ConfigurationError } from "@pipedream/platform";
7
- import { DATE_RANGE_OPTIONS } from "./common-constants.mjs";
7
+ import { DATE_RANGE_OPTIONS } from "../../common/constants.mjs";
8
8
  import { checkPrefix } from "../../common/utils.mjs";
9
9
 
10
10
  const RESOURCES = [
@@ -14,16 +14,17 @@ const RESOURCES = [
14
14
  customer,
15
15
  ];
16
16
 
17
+ // Action kept for backwards compatibility - prefer the individual resource-specific actions
17
18
  export default {
18
19
  ...common,
19
20
  key: "google_ads-create-report",
20
21
  name: "Create Report",
21
22
  description: "Generates a report from your Google Ads data. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
22
- version: "0.1.5",
23
+ version: "0.1.6",
23
24
  annotations: {
24
25
  destructiveHint: false,
25
26
  openWorldHint: true,
26
- readOnlyHint: false,
27
+ readOnlyHint: true,
27
28
  },
28
29
  type: "action",
29
30
  props: {
@@ -9,7 +9,7 @@ export default {
9
9
  key: "google_ads-generate-keyword-ideas",
10
10
  name: "Generate Keyword Ideas",
11
11
  description: `Generate keyword ideas using the Google Ads API. [See the documentation](${docLink})`,
12
- version: "0.0.1",
12
+ version: "0.0.2",
13
13
  type: "action",
14
14
  annotations: {
15
15
  destructiveHint: false,
@@ -0,0 +1,24 @@
1
+ import google_ads from "../../google_ads.app.mjs";
2
+
3
+ export default {
4
+ key: "google_ads-list-account-id-options",
5
+ name: "List Account ID Options",
6
+ description: "Retrieves available options for the Account ID field.",
7
+ version: "0.0.1",
8
+ type: "action",
9
+ annotations: {
10
+ destructiveHint: false,
11
+ openWorldHint: true,
12
+ readOnlyHint: true,
13
+ },
14
+ props: {
15
+ google_ads,
16
+ },
17
+ async run({ $ }) {
18
+ const options = await google_ads.propDefinitions.accountId.options.call(this.google_ads);
19
+ $.export("$summary", `Successfully retrieved ${options.length} option${options.length === 1
20
+ ? ""
21
+ : "s"}`);
22
+ return options;
23
+ },
24
+ };
@@ -8,7 +8,7 @@ export default {
8
8
  key: "google_ads-send-offline-conversion",
9
9
  name: "Send Offline Conversion",
10
10
  description: "Send an event to Google Ads to track offline conversions. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/ConversionAction)",
11
- version: "0.0.7",
11
+ version: "0.0.8",
12
12
  annotations: {
13
13
  destructiveHint: false,
14
14
  openWorldHint: true,
@@ -0,0 +1,193 @@
1
+ import { ConfigurationError } from "@pipedream/platform";
2
+ import googleAds from "../google_ads.app.mjs";
3
+ import props from "./props.mjs";
4
+ import {
5
+ CORE_DATE_SEGMENTS, DATE_RANGE_OPTIONS,
6
+ } from "./constants.mjs";
7
+ import { checkPrefix } from "./utils.mjs";
8
+
9
+ export function createReportComponent(resource) {
10
+ const {
11
+ label, value,
12
+ } = resource.resourceOption;
13
+
14
+ return {
15
+ props: {
16
+ ...props,
17
+ docsAlert: {
18
+ type: "alert",
19
+ alertType: "info",
20
+ content: `[See the documentation](https://developers.google.com/google-ads/api/fields/v21/${value}) for more information on available fields, segments and metrics.`,
21
+ },
22
+ objectFilter: {
23
+ propDefinition: [
24
+ googleAds,
25
+ "reportResourceFilter",
26
+ ({
27
+ accountId, customerClientId,
28
+ }) => ({
29
+ accountId,
30
+ customerClientId,
31
+ resource: value,
32
+ }),
33
+ ],
34
+ label: `${label}(s)`,
35
+ description: `Select the ${label}(s) to generate a report for (or leave blank for all ${label}s)`,
36
+ },
37
+ dateRange: {
38
+ type: "string",
39
+ label: "Date Range",
40
+ description: "Select a date range for the report",
41
+ options: DATE_RANGE_OPTIONS,
42
+ optional: true,
43
+ },
44
+ startDate: {
45
+ type: "string",
46
+ label: "Custom Start Date",
47
+ description: "If using a custom date range, this is the start date in `YYYY-MM-DD` format",
48
+ optional: true,
49
+ },
50
+ endDate: {
51
+ type: "string",
52
+ label: "Custom End Date",
53
+ description: "If using a custom date range, this is the end date in `YYYY-MM-DD` format",
54
+ optional: true,
55
+ },
56
+ fields: {
57
+ type: "string[]",
58
+ label: `${label} Fields`,
59
+ description: `Select the ${label} fields to include in the report`,
60
+ options: resource.fields,
61
+ optional: true,
62
+ },
63
+ segments: {
64
+ type: "string[]",
65
+ label: "Segments",
66
+ description: "Select any segments to include in the report. See the documentation [here](https://developers.google.com/google-ads/api/reference/rpc/v21/Segments)",
67
+ options: resource.segments,
68
+ default: [
69
+ "segments.date",
70
+ ],
71
+ optional: true,
72
+ },
73
+ metrics: {
74
+ type: "string[]",
75
+ label: "Metrics",
76
+ description: "Select any metrics to include in the report. See the documentation [here](https://developers.google.com/google-ads/api/reference/rpc/v21/Metrics)",
77
+ options: resource.metrics,
78
+ optional: true,
79
+ },
80
+ orderBy: {
81
+ propDefinition: [
82
+ googleAds,
83
+ "reportOrderBy",
84
+ ({
85
+ fields, segments, metrics, dateRange,
86
+ }) => ({
87
+ fields,
88
+ segments,
89
+ metrics,
90
+ dateRange,
91
+ }),
92
+ ],
93
+ },
94
+ direction: {
95
+ type: "string",
96
+ label: "Direction",
97
+ description: "If **Order By** is specified, this is the direction to order the results by",
98
+ optional: true,
99
+ options: [
100
+ {
101
+ label: "Ascending",
102
+ value: "ASC",
103
+ },
104
+ {
105
+ label: "Descending",
106
+ value: "DESC",
107
+ },
108
+ ],
109
+ default: "ASC",
110
+ },
111
+ limit: {
112
+ type: "integer",
113
+ label: "Limit",
114
+ description: "The maximum number of results to return",
115
+ optional: true,
116
+ },
117
+ },
118
+ methods: {
119
+ buildQuery() {
120
+ const {
121
+ fields, segments, metrics, limit, orderBy, direction, objectFilter, dateRange,
122
+ } = this;
123
+
124
+ const filteredSegments = dateRange
125
+ ? segments
126
+ : segments?.filter((s) => !CORE_DATE_SEGMENTS.includes(s));
127
+
128
+ const selection = [
129
+ ...checkPrefix(fields, value),
130
+ ...checkPrefix(filteredSegments, "segments"),
131
+ ...checkPrefix(metrics, "metrics"),
132
+ ];
133
+
134
+ if (!selection.length) {
135
+ throw new ConfigurationError("Select at least one field, segment or metric.");
136
+ }
137
+
138
+ if (dateRange === "CUSTOM" && (!this.startDate || !this.endDate)) {
139
+ throw new ConfigurationError("Both **Custom Start Date** and **Custom End Date** are required when using a custom date range.");
140
+ }
141
+
142
+ if (!dateRange && orderBy && CORE_DATE_SEGMENTS.includes(orderBy)) {
143
+ throw new ConfigurationError(`Cannot order by "${orderBy}" without a date range. Either select a **Date Range** or choose a different **Order By** field.`);
144
+ }
145
+
146
+ let query = `SELECT ${selection.join(", ")} FROM ${value}`;
147
+ if (objectFilter?.length) {
148
+ query += ` WHERE ${value === "ad_group_ad"
149
+ ? "ad_group_ad.ad"
150
+ : value}.id IN (${objectFilter.join?.(", ") ?? objectFilter})`;
151
+ }
152
+ if (dateRange) {
153
+ const dateClause = dateRange === "CUSTOM"
154
+ ? `BETWEEN '${this.startDate}' AND '${this.endDate}'`
155
+ : `DURING ${dateRange}`;
156
+ query += ` ${objectFilter
157
+ ? "AND"
158
+ : "WHERE"} segments.date ${dateClause}`;
159
+ }
160
+
161
+ if (orderBy && direction) {
162
+ query += ` ORDER BY ${orderBy} ${direction}`;
163
+ }
164
+ if (limit) {
165
+ query += ` LIMIT ${limit}`;
166
+ }
167
+
168
+ return query;
169
+ },
170
+ },
171
+ async run({ $ }) {
172
+ const query = this.buildQuery();
173
+ const results = (await this.googleAds.createReport({
174
+ $,
175
+ accountId: this.accountId,
176
+ customerClientId: this.customerClientId,
177
+ data: {
178
+ query,
179
+ },
180
+ })) ?? [];
181
+
182
+ const { length } = results;
183
+
184
+ $.export("$summary", `Successfully obtained ${length} result${length === 1
185
+ ? ""
186
+ : "s"}`);
187
+ return {
188
+ query,
189
+ results,
190
+ };
191
+ },
192
+ };
193
+ }
@@ -1,3 +1,11 @@
1
+ export const CORE_DATE_SEGMENTS = [
2
+ "segments.date",
3
+ "segments.week",
4
+ "segments.month",
5
+ "segments.quarter",
6
+ "segments.year",
7
+ ];
8
+
1
9
  export const DATE_RANGE_OPTIONS = [
2
10
  {
3
11
  value: "CUSTOM",
package/common/utils.mjs CHANGED
@@ -38,6 +38,36 @@ export function getOption(label, prefix) {
38
38
  };
39
39
  }
40
40
 
41
+ export function getResourceOption(item, resource) {
42
+ let label, value;
43
+ switch (resource) {
44
+ case "campaign":
45
+ label = item.campaign.name;
46
+ value = item.campaign.id;
47
+ break;
48
+
49
+ case "customer":
50
+ label = item.customer.descriptiveName;
51
+ value = item.customer.id;
52
+ break;
53
+
54
+ case "ad_group":
55
+ label = item.adGroup.name;
56
+ value = item.adGroup.id;
57
+ break;
58
+
59
+ case "ad_group_ad":
60
+ label = item.adGroupAd.ad.name;
61
+ value = item.adGroupAd.ad.id;
62
+ break;
63
+ }
64
+
65
+ return {
66
+ label,
67
+ value,
68
+ };
69
+ }
70
+
41
71
  export function checkPrefix(value, prefix) {
42
72
  const checkStr = (s) => s && (s?.startsWith?.(prefix)
43
73
  ? s
@@ -1,5 +1,7 @@
1
1
  import { axios } from "@pipedream/platform";
2
+ import { CORE_DATE_SEGMENTS } from "./common/constants.mjs";
2
3
  import { QUERIES } from "./common/queries.mjs";
4
+ import { getResourceOption } from "./common/utils.mjs";
3
5
 
4
6
  export default {
5
7
  type: "app",
@@ -68,6 +70,60 @@ export default {
68
70
  })).filter(({ value }) => value !== accountId);
69
71
  },
70
72
  },
73
+ reportResourceFilter: {
74
+ type: "string[]",
75
+ label: "Filter by Resources",
76
+ description: "Select the resources to generate a report for (or leave blank for all)",
77
+ optional: true,
78
+ useQuery: true,
79
+ async options({
80
+ accountId, customerClientId, resource, query, prevContext,
81
+ }) {
82
+ const pageToken = prevContext?.nextPageToken;
83
+ const {
84
+ results, nextPageToken,
85
+ } = await this.listResources({
86
+ accountId,
87
+ customerClientId,
88
+ resource,
89
+ query,
90
+ pageToken,
91
+ });
92
+ const options = results?.map?.((item) => this.getResourceOption(item, resource));
93
+ return {
94
+ options,
95
+ context: {
96
+ nextPageToken,
97
+ },
98
+ };
99
+ },
100
+ },
101
+ reportOrderBy: {
102
+ type: "string",
103
+ label: "Order By",
104
+ description: "The field to order the results by",
105
+ optional: true,
106
+ options({
107
+ fields, segments, metrics, dateRange,
108
+ }) {
109
+ return [
110
+ fields,
111
+ segments,
112
+ metrics,
113
+ ].filter((v) => v).flatMap((value) => {
114
+ let returnValue = value;
115
+ if (typeof value === "string") {
116
+ try {
117
+ returnValue = JSON.parse(value);
118
+ } catch (err) {
119
+ returnValue = value.split(",");
120
+ }
121
+ }
122
+ return returnValue?.map?.((str) => str.trim());
123
+ })
124
+ .filter((v) => dateRange || !CORE_DATE_SEGMENTS.includes(v));
125
+ },
126
+ },
71
127
  leadFormId: {
72
128
  type: "string",
73
129
  label: "Lead Form ID",
@@ -93,6 +149,7 @@ export default {
93
149
  },
94
150
  },
95
151
  methods: {
152
+ getResourceOption,
96
153
  _baseUrl() {
97
154
  return "https://googleads.m.pipedream.net";
98
155
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/google_ads",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Pipedream Google Ads Components",
5
5
  "main": "google_ads.app.mjs",
6
6
  "keywords": [
@@ -7,7 +7,7 @@ export default {
7
7
  key: "google_ads-new-campaign-created",
8
8
  name: "New Campaign Created",
9
9
  description: "Emit new event when a new campaign is created. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
10
- version: "0.0.6",
10
+ version: "0.0.7",
11
11
  type: "source",
12
12
  dedupe: "unique",
13
13
  sampleEmit,
@@ -8,7 +8,7 @@ export default {
8
8
  key: "google_ads-new-lead-form-entry",
9
9
  name: "New Lead Form Entry",
10
10
  description: "Emit new event for new leads on a Lead Form. [See the documentation](https://developers.google.com/google-ads/api/reference/rpc/v21/GoogleAdsService/Search?transport=rest)",
11
- version: "0.0.6",
11
+ version: "0.0.7",
12
12
  type: "source",
13
13
  dedupe: "unique",
14
14
  sampleEmit,