@google-cloud/nodejs-common 1.3.0 → 1.3.9-beta
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 +17 -17
- package/src/apis/google_ads.js +100 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@google-cloud/nodejs-common",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.9-beta",
|
|
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,25 +16,25 @@
|
|
|
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": "^
|
|
20
|
-
"@google-cloud/automl": "^
|
|
21
|
-
"@google-cloud/bigquery": "^6.0.
|
|
22
|
-
"@google-cloud/datastore": "^
|
|
23
|
-
"@google-cloud/firestore": "^
|
|
24
|
-
"@google-cloud/logging-winston": "^5.1.
|
|
25
|
-
"@google-cloud/pubsub": "^3.0
|
|
26
|
-
"@google-cloud/storage": "^6.
|
|
27
|
-
"@google-cloud/scheduler": "^3.0.
|
|
28
|
-
"gaxios": "^5.0.
|
|
29
|
-
"google-ads-api": "^11.
|
|
30
|
-
"google-ads-node": "^9.
|
|
31
|
-
"google-auth-library": "^8.
|
|
32
|
-
"googleapis": "^
|
|
33
|
-
"winston": "^3.
|
|
19
|
+
"@google-cloud/aiplatform": "^2.3.0",
|
|
20
|
+
"@google-cloud/automl": "^3.1.0",
|
|
21
|
+
"@google-cloud/bigquery": "^6.0.3",
|
|
22
|
+
"@google-cloud/datastore": "^7.0.0",
|
|
23
|
+
"@google-cloud/firestore": "^6.3.0",
|
|
24
|
+
"@google-cloud/logging-winston": "^5.1.5",
|
|
25
|
+
"@google-cloud/pubsub": "^3.2.0",
|
|
26
|
+
"@google-cloud/storage": "^6.5.2",
|
|
27
|
+
"@google-cloud/scheduler": "^3.0.4",
|
|
28
|
+
"gaxios": "^5.0.2",
|
|
29
|
+
"google-ads-api": "^11.1.0",
|
|
30
|
+
"google-ads-node": "^9.1.0",
|
|
31
|
+
"google-auth-library": "^8.5.2",
|
|
32
|
+
"googleapis": "^108.0.0",
|
|
33
|
+
"winston": "^3.8.2",
|
|
34
34
|
"lodash": "^4.17.21"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"jasmine": "^4.
|
|
37
|
+
"jasmine": "^4.4.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"test": "node node_modules/jasmine/bin/jasmine"
|
package/src/apis/google_ads.js
CHANGED
|
@@ -28,6 +28,7 @@ const {
|
|
|
28
28
|
resources: {
|
|
29
29
|
GoogleAdsField,
|
|
30
30
|
OfflineUserDataJob,
|
|
31
|
+
UserList,
|
|
31
32
|
},
|
|
32
33
|
services: {
|
|
33
34
|
CreateOfflineUserDataJobRequest,
|
|
@@ -50,6 +51,9 @@ const {
|
|
|
50
51
|
enums: {
|
|
51
52
|
OfflineUserDataJobTypeEnum: { OfflineUserDataJobType },
|
|
52
53
|
OfflineUserDataJobStatusEnum: { OfflineUserDataJobStatus },
|
|
54
|
+
UserListMembershipStatusEnum: { UserListMembershipStatus },
|
|
55
|
+
UserListTypeEnum: { UserListType },
|
|
56
|
+
CustomerMatchUploadKeyTypeEnum: { CustomerMatchUploadKeyType },
|
|
53
57
|
},
|
|
54
58
|
} = googleAdsLib;
|
|
55
59
|
const {GoogleAdsApi} = require('google-ads-api');
|
|
@@ -154,13 +158,18 @@ let ConversionConfig;
|
|
|
154
158
|
/**
|
|
155
159
|
* Configuration for uploading customer match to Google Ads, includes:
|
|
156
160
|
* customer_id, login_customer_id, list_id and operation.
|
|
161
|
+
* If audience list_id is not present, 'list_name' and 'upload_key_type' need to
|
|
162
|
+
* be there so they can be used to create a customer match user list.
|
|
157
163
|
* operation must be one of the two: 'create' or 'remove'.
|
|
158
164
|
* @see https://developers.google.com/google-ads/api/reference/rpc/latest/UserDataOperation
|
|
165
|
+
* @see https://developers.google.com/google-ads/api/reference/rpc/latest/CustomerMatchUploadKeyTypeEnum.CustomerMatchUploadKeyType
|
|
159
166
|
* @typedef {{
|
|
160
|
-
* customer_id: string,
|
|
161
|
-
* login_customer_id: string,
|
|
162
|
-
* list_id: string,
|
|
163
|
-
*
|
|
167
|
+
* customer_id: (string|number),
|
|
168
|
+
* login_customer_id: (string|number),
|
|
169
|
+
* list_id: (string|undefined),
|
|
170
|
+
* list_name: (string|undefined),
|
|
171
|
+
* upload_key_type: ('CONTACT_INFO'|'CRM_ID'|'MOBILE_ADVERTISING_ID'|undefined),
|
|
172
|
+
* operation: ('create'|'remove'),
|
|
164
173
|
* }}
|
|
165
174
|
*/
|
|
166
175
|
let CustomerMatchConfig;
|
|
@@ -171,12 +180,17 @@ let CustomerMatchConfig;
|
|
|
171
180
|
* 'operation' should be one of the two: 'create' or 'remove',
|
|
172
181
|
* 'type' is OfflineUserDataJobType, it can be 'CUSTOMER_MATCH_USER_LIST' or
|
|
173
182
|
* 'STORE_SALES_UPLOAD_FIRST_PARTY'.
|
|
183
|
+
* For job type 'CUSTOMER_MATCH_USER_LIST', if `list_id` is not present,
|
|
184
|
+
* 'list_name' and 'upload_key_type' need to be there so they can be used to
|
|
185
|
+
* create a customer match user list.
|
|
174
186
|
* @see https://developers.google.com/google-ads/api/reference/rpc/latest/OfflineUserDataJob
|
|
175
187
|
* @typedef {{
|
|
176
|
-
* customer_id: string,
|
|
177
|
-
* login_customer_id: string,
|
|
178
|
-
* list_id: (undefined
|
|
179
|
-
*
|
|
188
|
+
* customer_id: (string|number),
|
|
189
|
+
* login_customer_id: (string|number),
|
|
190
|
+
* list_id: (string|undefined),
|
|
191
|
+
* list_name: (string|undefined),
|
|
192
|
+
* upload_key_type: ('CONTACT_INFO'|'CRM_ID'|'MOBILE_ADVERTISING_ID'|undefined),
|
|
193
|
+
* operation: ('create'|'remove'),
|
|
180
194
|
* type: !OfflineUserDataJobType,
|
|
181
195
|
* storeSalesMetadata: (undefined|object),
|
|
182
196
|
* }}
|
|
@@ -624,6 +638,83 @@ class GoogleAds {
|
|
|
624
638
|
}
|
|
625
639
|
}
|
|
626
640
|
|
|
641
|
+
/**
|
|
642
|
+
* Gets the user list_id of a given list name and upload key type. It
|
|
643
|
+
* only looks for a CRM_BASED and OPEN list.
|
|
644
|
+
* @param {!CustomerMatchConfig} customerMatchConfig
|
|
645
|
+
* @return {number|undefined} User list_id if it exists.
|
|
646
|
+
*/
|
|
647
|
+
async getCustomerMatchUserListId(customerMatchConfig) {
|
|
648
|
+
const customerId = this.getCleanCid_(customerMatchConfig.customer_id);
|
|
649
|
+
const loginCustomerId = this.getCleanCid_(
|
|
650
|
+
customerMatchConfig.login_customer_id);
|
|
651
|
+
const listName = customerMatchConfig.list_name;
|
|
652
|
+
const uploadKeyType = customerMatchConfig.upload_key_type;
|
|
653
|
+
const reportConfig = {
|
|
654
|
+
entity: 'user_list',
|
|
655
|
+
attributes: [
|
|
656
|
+
'user_list.id',
|
|
657
|
+
'user_list.resource_name',
|
|
658
|
+
],
|
|
659
|
+
constraints: {
|
|
660
|
+
'user_list.name': listName,
|
|
661
|
+
'customer.id': customerId,
|
|
662
|
+
'user_list.type': UserListType.CRM_BASED,
|
|
663
|
+
'user_list.membership_status': UserListMembershipStatus.OPEN,
|
|
664
|
+
'user_list.crm_based_user_list.upload_key_type': uploadKeyType,
|
|
665
|
+
},
|
|
666
|
+
};
|
|
667
|
+
const userlists =
|
|
668
|
+
await this.getReport(customerId, loginCustomerId, reportConfig);
|
|
669
|
+
return userlists.length === 0 ? undefined : userlists[0].user_list.id;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Creates the user list based on a given customerMatchConfig and returns the
|
|
674
|
+
* Id. The user list would be a CRM_BASED type.
|
|
675
|
+
* Trying to create a list with an used name will fail.
|
|
676
|
+
* @param {!CustomerMatchConfig} customerMatchConfig
|
|
677
|
+
* @return {number} The created user list id. Note this is not the resource
|
|
678
|
+
* name.
|
|
679
|
+
*/
|
|
680
|
+
async createCustomerMatchUserList(customerMatchConfig) {
|
|
681
|
+
const customerId = this.getCleanCid_(customerMatchConfig.customer_id);
|
|
682
|
+
const loginCustomerId = this.getCleanCid_(
|
|
683
|
+
customerMatchConfig.login_customer_id);
|
|
684
|
+
const listName = customerMatchConfig.list_name;
|
|
685
|
+
const uploadKeyType = customerMatchConfig.upload_key_type;
|
|
686
|
+
const userList = UserList.create({
|
|
687
|
+
name: listName,
|
|
688
|
+
type: UserListType.CRM_BASED,
|
|
689
|
+
crm_based_user_list: { upload_key_type: uploadKeyType },
|
|
690
|
+
});
|
|
691
|
+
const options = {
|
|
692
|
+
validate_only: this.debugMode, // when true makes no changes
|
|
693
|
+
partial_failure: true, // Will still create the non-failed entities
|
|
694
|
+
};
|
|
695
|
+
const customer = this.getGoogleAdsApiCustomer_(loginCustomerId, customerId);
|
|
696
|
+
const response = await customer.userLists.create([userList], options);
|
|
697
|
+
const { results, partial_failure_error: failed } = response;
|
|
698
|
+
if (this.logger.isDebugEnabled()) {
|
|
699
|
+
this.logger.debug(`Created crm userlist from`, customerMatchConfig);
|
|
700
|
+
}
|
|
701
|
+
if (failed) {
|
|
702
|
+
const failures = failed.errors.map(({ message }) => message).join(' ');
|
|
703
|
+
this.logger.info('partial_failure_error:', failures);
|
|
704
|
+
throw new Error(failures);
|
|
705
|
+
}
|
|
706
|
+
if (!results[0]) {
|
|
707
|
+
if (this.debugMode) {
|
|
708
|
+
throw new Error('No UserList was created in DEBUG mode.');
|
|
709
|
+
} else {
|
|
710
|
+
throw new Error('No UserList was created.');
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
const resourceName = results[0].resource_name;
|
|
714
|
+
const splitted = resourceName.split('/');
|
|
715
|
+
return splitted[splitted.length - 1];
|
|
716
|
+
}
|
|
717
|
+
|
|
627
718
|
/**
|
|
628
719
|
* Returns the function to send out a request to Google Ads API with
|
|
629
720
|
* user ids for Customer Match upload
|
|
@@ -792,8 +883,6 @@ class GoogleAds {
|
|
|
792
883
|
return OfflineUserDataJobStatus[jobs[0].offline_user_data_job.status];
|
|
793
884
|
}
|
|
794
885
|
|
|
795
|
-
//resource_name: 'customers/8368692804/offlineUserDataJobs/23130531867'
|
|
796
|
-
//'customers/8368692804/offlineUserDataJobs/23232922761'
|
|
797
886
|
/**
|
|
798
887
|
* Creates a OfflineUserDataJob and returns resource name.
|
|
799
888
|
* @param {OfflineUserDataJobConfig} config Offline user data job config.
|
|
@@ -818,7 +907,7 @@ class GoogleAds {
|
|
|
818
907
|
} else if (type.startsWith('STORE_SALES')) {
|
|
819
908
|
// If there is StoreSalesMetadata in the config
|
|
820
909
|
if (config.storeSalesMetadata) {
|
|
821
|
-
job.
|
|
910
|
+
job.store_sales_metadata = config.storeSalesMetadata;
|
|
822
911
|
}
|
|
823
912
|
} else {
|
|
824
913
|
throw new Error(`UNSUPPORTED OfflineUserDataJobType: ${type}.`);
|