@google-cloud/nodejs-common 1.5.7-beta → 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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@google-cloud/nodejs-common",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "A NodeJs common library for solutions based on Cloud Functions",
|
|
5
5
|
"author": "Google Inc.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,21 +16,21 @@
|
|
|
16
16
|
},
|
|
17
17
|
"homepage": "https://github.com/GoogleCloudPlatform/cloud-for-marketing/blob/master/marketing-analytics/activation/common-libs/nodejs-common/README.md",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@google-cloud/aiplatform": "^2.
|
|
20
|
-
"@google-cloud/automl": "^3.1.
|
|
21
|
-
"@google-cloud/bigquery": "^6.0
|
|
22
|
-
"@google-cloud/datastore": "^7.
|
|
23
|
-
"@google-cloud/firestore": "^6.
|
|
24
|
-
"@google-cloud/logging-winston": "^5.
|
|
25
|
-
"@google-cloud/pubsub": "^3.
|
|
26
|
-
"@google-cloud/storage": "^6.
|
|
27
|
-
"@google-cloud/scheduler": "^3.0
|
|
28
|
-
"@google-cloud/secret-manager": "^4.
|
|
19
|
+
"@google-cloud/aiplatform": "^2.5.0",
|
|
20
|
+
"@google-cloud/automl": "^3.1.2",
|
|
21
|
+
"@google-cloud/bigquery": "^6.1.0",
|
|
22
|
+
"@google-cloud/datastore": "^7.1.0",
|
|
23
|
+
"@google-cloud/firestore": "^6.4.2",
|
|
24
|
+
"@google-cloud/logging-winston": "^5.3.0",
|
|
25
|
+
"@google-cloud/pubsub": "^3.3.0",
|
|
26
|
+
"@google-cloud/storage": "^6.9.2",
|
|
27
|
+
"@google-cloud/scheduler": "^3.2.0",
|
|
28
|
+
"@google-cloud/secret-manager": "^4.2.0",
|
|
29
29
|
"gaxios": "^5.0.2",
|
|
30
|
-
"google-ads-api": "^
|
|
31
|
-
"google-ads-node": "^
|
|
32
|
-
"google-auth-library": "^8.
|
|
33
|
-
"googleapis": "^
|
|
30
|
+
"google-ads-api": "^12.0.1",
|
|
31
|
+
"google-ads-node": "^10.0.0",
|
|
32
|
+
"google-auth-library": "^8.7.0",
|
|
33
|
+
"googleapis": "^110.0.0",
|
|
34
34
|
"winston": "^3.8.2",
|
|
35
35
|
"lodash": "^4.17.21"
|
|
36
36
|
},
|
|
@@ -284,6 +284,10 @@ class DfaReporting {
|
|
|
284
284
|
* Runs a report and return the file Id. As an asynchronized process, the
|
|
285
285
|
* returned file Id will be a placeholder until the status changes to
|
|
286
286
|
* 'REPORT_AVAILABLE' in the response of `getFile`.
|
|
287
|
+
* Campaign Manager reports use a fixed timezone(America/Los Angeles) when it
|
|
288
|
+
* has a relative date range, e.g. YESTERDAY. To solve this, if there are
|
|
289
|
+
* `startDate` and `endDate` available in the given `config`, they will be
|
|
290
|
+
* used to update the report before the report is started to run.
|
|
287
291
|
* @see https://developers.google.com/doubleclick-advertisers/rest/v4/reports/run
|
|
288
292
|
*
|
|
289
293
|
* @param {{
|
|
@@ -296,6 +300,24 @@ class DfaReporting {
|
|
|
296
300
|
async runReport(config) {
|
|
297
301
|
const profileId = await this.getProfileForOperation_(config);
|
|
298
302
|
const dfareporting = await this.getApiClient_();
|
|
303
|
+
const { startDate, endDate } = config;
|
|
304
|
+
if (startDate && endDate) {
|
|
305
|
+
const { data: report } = await dfareporting.reports.get({
|
|
306
|
+
profileId,
|
|
307
|
+
reportId: config.reportId,
|
|
308
|
+
});
|
|
309
|
+
report.criteria.dateRange = { startDate, endDate };
|
|
310
|
+
const updated = await dfareporting.reports.update({
|
|
311
|
+
profileId,
|
|
312
|
+
reportId: config.reportId,
|
|
313
|
+
requestBody: report
|
|
314
|
+
});
|
|
315
|
+
if (updated.status >= 400) {
|
|
316
|
+
this.logger.error(
|
|
317
|
+
'Failed to update data range of CM360 report', config.reportId);
|
|
318
|
+
this.logger.error('Report to be updated', report);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
299
321
|
const response = await dfareporting.reports.run({
|
|
300
322
|
profileId,
|
|
301
323
|
reportId: config.reportId,
|
package/src/apis/google_ads.js
CHANGED
|
@@ -21,9 +21,12 @@ const {protos: {google: {ads: {googleads}}}} = require('google-ads-node');
|
|
|
21
21
|
const googleAdsLib = googleads[Object.keys(googleads)[0]];
|
|
22
22
|
const {
|
|
23
23
|
common: {
|
|
24
|
+
CustomerMatchUserListMetadata,
|
|
25
|
+
StoreSalesMetadata,
|
|
26
|
+
TransactionAttribute,
|
|
27
|
+
UserAttribute,
|
|
24
28
|
UserData,
|
|
25
29
|
UserIdentifier,
|
|
26
|
-
CustomerMatchUserListMetadata,
|
|
27
30
|
},
|
|
28
31
|
resources: {
|
|
29
32
|
GoogleAdsField,
|
|
@@ -31,24 +34,25 @@ const {
|
|
|
31
34
|
UserList,
|
|
32
35
|
},
|
|
33
36
|
services: {
|
|
34
|
-
CreateOfflineUserDataJobRequest,
|
|
35
37
|
AddOfflineUserDataJobOperationsRequest,
|
|
38
|
+
CreateOfflineUserDataJobRequest,
|
|
36
39
|
RunOfflineUserDataJobRequest,
|
|
40
|
+
SearchGoogleAdsFieldsRequest,
|
|
37
41
|
UploadCallConversionsRequest,
|
|
38
|
-
UploadClickConversionsRequest,
|
|
39
42
|
UploadCallConversionsResponse,
|
|
43
|
+
UploadClickConversionsRequest,
|
|
40
44
|
UploadClickConversionsResponse,
|
|
41
45
|
UploadConversionAdjustmentsRequest,
|
|
42
46
|
UploadConversionAdjustmentsResponse,
|
|
43
47
|
UploadUserDataRequest,
|
|
44
48
|
UploadUserDataResponse,
|
|
45
49
|
UserDataOperation,
|
|
46
|
-
SearchGoogleAdsFieldsRequest,
|
|
47
50
|
},
|
|
48
51
|
errors: {
|
|
49
52
|
GoogleAdsFailure,
|
|
50
53
|
},
|
|
51
54
|
enums: {
|
|
55
|
+
OfflineUserDataJobFailureReasonEnum: { OfflineUserDataJobFailureReason },
|
|
52
56
|
OfflineUserDataJobTypeEnum: { OfflineUserDataJobType },
|
|
53
57
|
OfflineUserDataJobStatusEnum: { OfflineUserDataJobStatus },
|
|
54
58
|
UserListMembershipStatusEnum: { UserListMembershipStatus },
|
|
@@ -77,6 +81,8 @@ const PICKED_PROPERTIES = [
|
|
|
77
81
|
'external_attribution_data',
|
|
78
82
|
'cart_data',
|
|
79
83
|
'user_identifiers',
|
|
84
|
+
'gbraid',
|
|
85
|
+
'wbraid',
|
|
80
86
|
'gclid',
|
|
81
87
|
'caller_id',
|
|
82
88
|
'call_start_date_time',
|
|
@@ -105,6 +111,16 @@ const IDENTIFIERS = [
|
|
|
105
111
|
'address_info',
|
|
106
112
|
];
|
|
107
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Additional attributes in user data for store sales data or customer match.
|
|
116
|
+
* @see https://developers.google.com/google-ads/api/reference/rpc/latest/UserData
|
|
117
|
+
* @type {Array<string>}
|
|
118
|
+
*/
|
|
119
|
+
const USERDATA_ADDITIONAL_ATTRIBUTES = [
|
|
120
|
+
'transaction_attribute',
|
|
121
|
+
'user_attribute',
|
|
122
|
+
];
|
|
123
|
+
|
|
108
124
|
/**
|
|
109
125
|
* Maximum number of user identifiers in single UserData.
|
|
110
126
|
* @see https://ads-developers.googleblog.com/2021/10/userdata-enforcement-in-google-ads-api.html
|
|
@@ -179,11 +195,17 @@ let CustomerMatchConfig;
|
|
|
179
195
|
* Configuration for offline user data job, includes:
|
|
180
196
|
* customer_id, login_customer_id, list_id, operation and type.
|
|
181
197
|
* 'operation' should be one of the two: 'create' or 'remove',
|
|
182
|
-
* 'type' is OfflineUserDataJobType, it can be 'CUSTOMER_MATCH_USER_LIST'
|
|
183
|
-
* 'STORE_SALES_UPLOAD_FIRST_PARTY'.
|
|
198
|
+
* 'type' is OfflineUserDataJobType, it can be 'CUSTOMER_MATCH_USER_LIST',
|
|
199
|
+
* 'CUSTOMER_MATCH_WITH_ATTRIBUTES' or 'STORE_SALES_UPLOAD_FIRST_PARTY'.
|
|
184
200
|
* For job type 'CUSTOMER_MATCH_USER_LIST', if `list_id` is not present,
|
|
185
201
|
* 'list_name' and 'upload_key_type' need to be there so they can be used to
|
|
186
202
|
* create a customer match user list.
|
|
203
|
+
* For job type 'CUSTOMER_MATCH_WITH_ATTRIBUTES', 'user_attribute' can be used
|
|
204
|
+
* to store shared additional user attributes.
|
|
205
|
+
* For job type 'STORE_SALES_UPLOAD_FIRST_PARTY', `store_sales_metadata` is
|
|
206
|
+
* required to offer StoreSalesMetadata. Besides that, for the store sales data,
|
|
207
|
+
* common data (e.g. `currency_code`, `conversion_action`) in
|
|
208
|
+
* `transaction_attribute` can be put here as well.
|
|
187
209
|
* @see https://developers.google.com/google-ads/api/reference/rpc/latest/OfflineUserDataJob
|
|
188
210
|
* @typedef {{
|
|
189
211
|
* customer_id: (string|number),
|
|
@@ -193,7 +215,9 @@ let CustomerMatchConfig;
|
|
|
193
215
|
* upload_key_type: ('CONTACT_INFO'|'CRM_ID'|'MOBILE_ADVERTISING_ID'|undefined),
|
|
194
216
|
* operation: ('create'|'remove'),
|
|
195
217
|
* type: !OfflineUserDataJobType,
|
|
196
|
-
*
|
|
218
|
+
* store_sales_metadata: (undefined|StoreSalesMetadata),
|
|
219
|
+
* transaction_attribute: (undefined|TransactionAttribute),
|
|
220
|
+
* user_attribute: (undefined|UserAttribute),
|
|
197
221
|
* }}
|
|
198
222
|
*/
|
|
199
223
|
let OfflineUserDataJobConfig;
|
|
@@ -802,10 +826,16 @@ class GoogleAds {
|
|
|
802
826
|
* @see https://developers.google.com/google-ads/api/reference/rpc/latest/UserDataOperation
|
|
803
827
|
* @param {string} operationType either 'create' or 'remove'
|
|
804
828
|
* @param {Array<CustomerMatchRecord>} customerMatchRecords userIds
|
|
829
|
+
* @param {{
|
|
830
|
+
* transaction_attribute: TransactionAttribute|undefined,
|
|
831
|
+
* user_attribute: UserAttribute,
|
|
832
|
+
* }} additionalAttributes Additional attributes for 'UserData', includes
|
|
833
|
+
* 'transaction_attribute' or 'user_attribute'.
|
|
805
834
|
* @return {Array<UserDataOperation>}
|
|
806
835
|
* @private
|
|
807
836
|
*/
|
|
808
|
-
buildOperationsList_(operationType, customerMatchRecords
|
|
837
|
+
buildOperationsList_(operationType, customerMatchRecords,
|
|
838
|
+
additionalAttributes = {}) {
|
|
809
839
|
return customerMatchRecords.map((customerMatchRecord) => {
|
|
810
840
|
const userIdentifiers = [];
|
|
811
841
|
IDENTIFIERS.forEach((idType) => {
|
|
@@ -820,17 +850,24 @@ class GoogleAds {
|
|
|
820
850
|
}
|
|
821
851
|
}
|
|
822
852
|
});
|
|
823
|
-
|
|
853
|
+
const userData = {};
|
|
824
854
|
if (userIdentifiers.length <= MAX_IDENTIFIERS_PER_USER) {
|
|
825
|
-
userData =
|
|
855
|
+
userData.user_identifiers = userIdentifiers;
|
|
826
856
|
} else {
|
|
827
857
|
this.logger.warn(
|
|
828
858
|
`Too many user identifiers, will only send ${MAX_IDENTIFIERS_PER_USER}:`,
|
|
829
859
|
JSON.stringify(customerMatchRecord));
|
|
830
|
-
userData
|
|
831
|
-
|
|
860
|
+
userData.user_identifiers =
|
|
861
|
+
userIdentifiers.slice(0, MAX_IDENTIFIERS_PER_USER);
|
|
832
862
|
}
|
|
833
|
-
|
|
863
|
+
USERDATA_ADDITIONAL_ATTRIBUTES.forEach((attribute) => {
|
|
864
|
+
if (additionalAttributes[attribute] || customerMatchRecord[attribute]) {
|
|
865
|
+
userData[attribute] = lodash.merge(
|
|
866
|
+
{}, additionalAttributes[attribute], customerMatchRecord[attribute]);
|
|
867
|
+
}
|
|
868
|
+
})
|
|
869
|
+
return UserDataOperation.create(
|
|
870
|
+
{ [operationType]: UserData.create(userData) });
|
|
834
871
|
});
|
|
835
872
|
}
|
|
836
873
|
|
|
@@ -885,7 +922,12 @@ class GoogleAds {
|
|
|
885
922
|
if (jobs.length === 0) {
|
|
886
923
|
throw new Error(`Can't find the OfflineUserDataJob: ${resourceName}`);
|
|
887
924
|
}
|
|
888
|
-
|
|
925
|
+
const { failure_reason: failure, status } = jobs[0].offline_user_data_job;
|
|
926
|
+
if (failure > 0) {
|
|
927
|
+
this.logger.warn(`Offline UserData Job [${resourceName}] failed: `,
|
|
928
|
+
OfflineUserDataJobFailureReason[failure])
|
|
929
|
+
}
|
|
930
|
+
return OfflineUserDataJobStatus[status];
|
|
889
931
|
}
|
|
890
932
|
|
|
891
933
|
/**
|
|
@@ -910,9 +952,10 @@ class GoogleAds {
|
|
|
910
952
|
job.customer_match_user_list_metadata = metadata;
|
|
911
953
|
// https://developers.google.com/google-ads/api/rest/reference/rest/latest/customers.offlineUserDataJobs?hl=en#StoreSalesMetadata
|
|
912
954
|
} else if (type.startsWith('STORE_SALES')) {
|
|
913
|
-
//
|
|
914
|
-
if (config.
|
|
915
|
-
job.store_sales_metadata = config.
|
|
955
|
+
// Support previous property 'StoreSalesMetadata' for compatibility.
|
|
956
|
+
if (config.store_sales_metadata || config.StoreSalesMetadata) {
|
|
957
|
+
job.store_sales_metadata = config.store_sales_metadata
|
|
958
|
+
|| config.StoreSalesMetadata;
|
|
916
959
|
}
|
|
917
960
|
} else {
|
|
918
961
|
throw new Error(`UNSUPPORTED OfflineUserDataJobType: ${type}.`);
|
|
@@ -943,7 +986,7 @@ class GoogleAds {
|
|
|
943
986
|
const operation = config.operation;
|
|
944
987
|
const customer = await this.getGoogleAdsApiCustomer_(
|
|
945
988
|
loginCustomerId, customerId);
|
|
946
|
-
const operationsList = this.buildOperationsList_(operation, records);
|
|
989
|
+
const operationsList = this.buildOperationsList_(operation, records, config);
|
|
947
990
|
const request = AddOfflineUserDataJobOperationsRequest.create({
|
|
948
991
|
resource_name: jobResourceName,
|
|
949
992
|
operations: operationsList,
|