Skip to content

Commit bd14929

Browse files
committed
remove console.log
1 parent 6daefd8 commit bd14929

File tree

25 files changed

+316
-63
lines changed

25 files changed

+316
-63
lines changed

.vscode/launch.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"request": "launch",
1010
"name": "Jest Current File",
1111
"program": "${workspaceFolder}/node_modules/.bin/jest",
12-
"args": ["${fileBasenameNoExtension}", "--config", "jest.config.js"],
12+
"args": ["${fileBasenameNoExtension}", "--config", "jest.config.js", "--detectOpenHandles"],
1313
"console": "integratedTerminal",
1414
"internalConsoleOptions": "neverOpen",
1515
"disableOptimisticBPs": true,

readme.md

+68-1
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,79 @@ ADWORDS_REFRESH_TOKEN=<OAuth Refresh Token>
4646

4747
Put above environment variables into `.env` file for local development.
4848

49+
## Usage
50+
51+
Initialize `AdwordsService` with above environment variables
52+
53+
```ts
54+
const adwordsService = new AdWordsService({
55+
clientCustomerId: credentials.ADWORDS_CLIENT_CUSTOMER_ID,
56+
developerToken: credentials.ADWORDS_DEVELOPER_TOKEN,
57+
userAgent: credentials.ADWORDS_USER_AGENT,
58+
clientId: credentials.ADWORDS_CLIENT_ID,
59+
clientSecret: credentials.ADWORDS_SECRET,
60+
credentials: {
61+
refresh_token: credentials.ADWORDS_REFRESH_TOKEN,
62+
},
63+
});
64+
```
65+
66+
Get budgets by page:
67+
68+
```ts
69+
async function getByPage() {
70+
const budgetService = adwordsService.getService('BudgetService');
71+
const paging: IPaging = {
72+
startIndex: 0,
73+
numberResults: 2,
74+
};
75+
const actualValue = await budgetService.getByPage(paging);
76+
}
77+
```
78+
79+
Create a budget:
80+
81+
```ts
82+
async function createBudget() {
83+
const budgetService = adwordsService.getService('BudgetService');
84+
85+
const budget: IBudget = {
86+
name: faker.lorem.word(),
87+
amount: {
88+
microAmount: BudgetService.UNIT,
89+
},
90+
deliveryMethod: Budget.BudgetDeliveryMethod.STANDARD,
91+
isExplicitlyShared: false,
92+
status: Budget.BudgetStatus.ENABLED,
93+
};
94+
95+
const actualValue = await budgetService.add(budget);
96+
}
97+
```
98+
99+
Get campaigns by page:
100+
101+
```ts
102+
async function getCampaignsByPages() {
103+
const paging: IPaging = {
104+
startIndex: 0,
105+
numberResults: 1,
106+
};
107+
const actualValue = await campaignService.getByPage(paging);
108+
}
109+
```
110+
111+
Same usage for other Google Adwords resources
112+
49113
## TODO
50114

51115
- [ ] <https://developers.google.com/adwords/api/docs/guides/batch-jobs>
52116
- [ ] <http://adwordsapi.blogspot.in/2011/03/concurrency-management-in-adwords-api.html>
117+
- [ ] Add model layer and object schema validation
118+
- [ ] Improve error handling
119+
- [ ] Improve `TypeScript` types
53120

54-
## references
121+
## References
55122

56123
- <https://developers.google.com/adwords/api/docs/reference/release-notes/v201809?refresh=1>
57124
- <https://github.com/googleads/googleads-python-lib/wiki>

src/__tests__/services/adwords/BudgetService/BudgetService.spec.ts

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import faker from 'faker';
22

33
import { adwordsService } from '../../initialize';
44
import { IPaging } from '../../../../types/adwords';
5-
import { BudgetService, Budget } from '../../../../services/adwords/BudgetService';
5+
import { BudgetService, Budget, IBudget } from '../../../../services/adwords/BudgetService';
66

77
describe('BudgetService test suites', () => {
88
const budgetService = adwordsService.getService('BudgetService', { verbose: false });
9-
it.skip('#getAll', async () => {
9+
it('#getAll', async () => {
1010
const actualValue = await budgetService.getAll();
1111
});
1212

13-
it('#getByPage', async () => {
13+
it.skip('#getByPage', async () => {
1414
const paging: IPaging = {
1515
startIndex: 0,
1616
numberResults: 2,
@@ -49,4 +49,9 @@ describe('BudgetService test suites', () => {
4949
};
5050
const actualValue = await budgetService.update(budget);
5151
});
52+
53+
it.skip('#remove', async () => {
54+
const budgetIds: string[] = ['1902117292'];
55+
const actualValue = await budgetService.remove(budgetIds);
56+
});
5257
});

src/__tests__/services/adwords/CampaignService/CampaignService.spec.ts

+58-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
1+
import faker from 'faker';
2+
import moment from 'moment';
3+
14
import { adwordsService } from '../../initialize';
25
import { IPaging } from '../../../../types/adwords';
36
import { ICampaignLabel } from '../../../../services/adwords/CampaignService/CampaignLabel';
7+
import {
8+
ICampaign,
9+
CampaignStatus,
10+
CampaignService,
11+
IBudget,
12+
AdvertisingChannelType,
13+
} from '../../../../services/adwords/CampaignService';
14+
import { TimeUnit, Level } from '../../../../services/adwords/CampaignService/FrequencyCap';
15+
import { IGeoTargetTypeSetting } from '../../../../services/adwords/CampaignService/Setting';
16+
import { GeoTargetTypeSetting } from '../../../../services/adwords/CampaignService/enum/GeoTargetTypeSetting';
17+
import { BiddingStrategyType } from '../../../../services/adwords/CampaignService/BiddingStrategyConfiguration';
418

519
describe('CampaignService test suites', () => {
620
const campaignService = adwordsService.getService('CampaignService', {
@@ -10,7 +24,7 @@ describe('CampaignService test suites', () => {
1024
const actualValue = await campaignService.getAll();
1125
});
1226

13-
it('#getByPage', async () => {
27+
it.skip('#getByPage', async () => {
1428
const paging: IPaging = {
1529
startIndex: 0,
1630
numberResults: 1,
@@ -35,6 +49,49 @@ describe('CampaignService test suites', () => {
3549
const actualValue = await campaignService.remove(campaignId);
3650
});
3751

52+
it('#add', async () => {
53+
const budget: IBudget = {
54+
budgetId: '1865779148',
55+
};
56+
const settings: IGeoTargetTypeSetting = {
57+
positiveGeoTargetType: GeoTargetTypeSetting.PositiveGeoTargetType.DONT_CARE,
58+
negativeGeoTargetType: GeoTargetTypeSetting.NegativeGeoTargetType.DONT_CARE,
59+
attributes: {
60+
'xsi:type': 'GeoTargetTypeSetting',
61+
},
62+
};
63+
const campaign: ICampaign = {
64+
name: faker.company.bs(),
65+
status: CampaignStatus.ENABLED,
66+
startDate: moment()
67+
.add(1, 'd')
68+
.format(CampaignService.dateFormat),
69+
endDate: moment()
70+
.add(2, 'd')
71+
.format(CampaignService.dateFormat),
72+
budget,
73+
biddingStrategyConfiguration: {
74+
biddingStrategyName: faker.lorem.word(),
75+
biddingStrategyType: BiddingStrategyType.MANUAL_CPC,
76+
},
77+
frequencyCap: {
78+
impressions: 10,
79+
timeUnit: TimeUnit.DAY,
80+
level: Level.CAMPAIGN,
81+
},
82+
settings,
83+
advertisingChannelType: AdvertisingChannelType.SEARCH,
84+
networkSetting: {
85+
targetContentNetwork: true,
86+
targetGoogleSearch: true,
87+
targetPartnerSearchNetwork: false,
88+
targetSearchNetwork: true,
89+
},
90+
};
91+
92+
const actualValue = await campaignService.add(campaign);
93+
});
94+
3895
it.skip('#addLabel', async () => {
3996
// properties order is important
4097
const campaignLabel: ICampaignLabel = {

src/__tests__/services/initialize.ts

-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ const adwordsService = new AdWordsService({
1010
credentials: {
1111
refresh_token: credentials.ADWORDS_REFRESH_TOKEN,
1212
},
13-
// validateOnly: true,
14-
// partialFailure: true
1513
});
1614
adwordsService.setVerbose(false);
1715

src/services/adwords/AdGroupAdService/Ad.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { IImage } from './Media';
88
import { IDynamicSettings } from './DynamicSettings';
99
import { DisplayAdFormatSetting } from './enum/DisplayAdFormatSetting';
1010

11-
interface IAdRaw<Type> {
11+
interface IAdRaw<Type> extends IAttributes<Type> {
1212
id: string;
1313
url: string;
1414
displayUrl: string;
@@ -24,7 +24,6 @@ interface IAdRaw<Type> {
2424
devicePreference: string;
2525
readonly systemManagedEntitySource: SystemManagedEntitySource;
2626
'Ad.Type': string;
27-
attributes: IAttributes<Type>;
2827
}
2928

3029
interface IAd<Type = ''> extends Partial<IAdRaw<Type>> {}

src/services/adwords/AdGroupAdService/Media.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { IMedia_Size_DimensionsMapEntry } from './Media_Size_DimensionsMapEntry'
33
import { IMedia_Size_StringMapEntry } from './Media_Size_StringMapEntry';
44
import { IAttributes } from '../../../types/adwords/Attributes';
55

6-
interface IMediaRaw<Type> {
6+
interface IMediaRaw<Type> extends IAttributes<Type> {
77
mediaId: string;
88
type: Media.MediaType;
99
referenceId: string;
@@ -15,7 +15,6 @@ interface IMediaRaw<Type> {
1515
fileSize: string;
1616
creationTime: string;
1717
'Media.Type': string;
18-
attributes: IAttributes<Type>;
1918
}
2019

2120
interface IMedia<Type> extends Partial<IMediaRaw<Type>> {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import { IOperation } from '../../../types/adwords';
22
import { IBiddableAdGroupCriterion, INegativeAdGroupCriterion } from './AdGroupCriterion';
33

4-
export interface IAdGroupCriterionOperation extends IOperation {
4+
export interface IAdGroupCriterionOperation extends IOperation<'AdGroupCriterionOperation'> {
55
operand: IBiddableAdGroupCriterion | INegativeAdGroupCriterion;
66
// TODO:
77
exemptionRequests?: any[];
8-
attributes?: {
9-
'xsi:type': 'AdGroupCriterionOperation';
10-
};
118
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { IOperation } from '../../../types/adwords';
22
import { IAdGroup } from './AdGroup';
33

4-
export interface IAdGroupOperation extends IOperation {
4+
export interface IAdGroupOperation extends IOperation<'AdGroupOperation'> {
55
operand: IAdGroup;
66
}

src/services/adwords/AdGroupService/index.ts

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ import { IAdGroup } from './AdGroup';
1010
interface IAdGroupServiceOpts {
1111
soapService: SoapService;
1212
}
13+
14+
/**
15+
* https://developers.google.com/adwords/api/docs/reference/v201809/AdGroupService
16+
*
17+
* @author dulin
18+
* @class AdGroupService
19+
* @extends {AdwordsOperartionService}
20+
*/
1321
class AdGroupService extends AdwordsOperartionService {
1422
/**
1523
* https://developers.google.com/adwords/api/docs/appendix/selectorfields?hl=zh-cn#v201809-AdGroupService
@@ -87,6 +95,9 @@ class AdGroupService extends AdwordsOperartionService {
8795
{
8896
operator: Operator.ADD,
8997
operand: adGroup,
98+
attributes: {
99+
'xsi:type': 'AdGroupOperation',
100+
},
90101
},
91102
];
92103
return this.mutate(operations);

src/services/adwords/BudgetService/index.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,14 @@ class BudgetService extends AdwordsOperartionService {
9696

9797
public async add(budget: IBudget) {
9898
// TODO: validate budget
99-
const operation: IBudgetOperation = {
100-
operator: Operator.ADD,
101-
operand: budget,
102-
};
103-
return this.mutate([operation]);
99+
// TODO: support multiple add
100+
const operations: IBudgetOperation[] = [
101+
{
102+
operator: Operator.ADD,
103+
operand: budget,
104+
},
105+
];
106+
return this.mutate(operations);
104107
}
105108

106109
public async update(budget: IBudget) {
@@ -111,6 +114,19 @@ class BudgetService extends AdwordsOperartionService {
111114
return this.mutate([operation]);
112115
}
113116

117+
public async remove(budgetIds: string[]) {
118+
const operations: IBudgetOperation[] = budgetIds.map((budgetId: string) => {
119+
const operand: IBudget = { budgetId };
120+
const operation: IBudgetOperation = {
121+
operator: Operator.REMOVE,
122+
operand,
123+
};
124+
return operation;
125+
});
126+
127+
return this.mutate(operations);
128+
}
129+
114130
protected async get<ServiceSelector = ISelector, Rval = IBudgetPage>(
115131
serviceSelector: ServiceSelector,
116132
): Promise<Rval | undefined> {
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { IOperation } from '../../../types/adwords';
22
import { INegativeCampaignCriterion, ICampaignCriterion } from './CampaignCriterion';
33

4-
export interface ICampaignCriterionOperation extends IOperation {
4+
export interface ICampaignCriterionOperation extends IOperation<'CampaignCriterionOperation'> {
55
operand: INegativeCampaignCriterion | ICampaignCriterion;
6-
attributes: {
7-
'xsi:type': 'CampaignCriterionOperation';
8-
};
96
}

src/services/adwords/CampaignService/BiddingStrategyConfiguration.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ enum BiddingStrategySource {
2121
}
2222

2323
interface IBiddingStrategyConfiguration {
24-
biddingStrategyId: string;
24+
biddingStrategyId?: string;
2525
biddingStrategyName: string;
2626
biddingStrategyType: BiddingStrategyType;
2727
readonly biddingStrategySource?: BiddingStrategySource;
2828
// TODO:
29-
biddingScheme: any;
30-
bids: Array<ICpcBid | ICpaBid | ICpmBid>;
31-
targetRoasOverride: number;
29+
biddingScheme?: any;
30+
bids?: Array<ICpcBid | ICpaBid | ICpmBid>;
31+
targetRoasOverride?: number;
3232
}
3333

34-
export { IBiddingStrategyConfiguration };
34+
export { IBiddingStrategyConfiguration, BiddingStrategyType };

src/services/adwords/CampaignService/Campaign.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { INetworkSetting } from './NetworkSetting';
33
import { ITextLabel } from './Label';
44
import { IFrequencyCap } from './FrequencyCap';
55
import { IConversionOptimizerEligibility } from './ConversionOptimizerEligibility';
6-
import { ISetting } from './Setting';
6+
import { IGeoTargetTypeSetting } from './Setting';
77
import { IBiddingStrategyConfiguration } from './BiddingStrategyConfiguration';
88
import { CampaignStatus } from './enum/CampaignStatus';
99
import { ServingStatus } from './enum/ServingStatus';
@@ -23,10 +23,11 @@ interface ICampaignRaw {
2323
startDate: string;
2424
endDate: string;
2525
budget: IBudget;
26-
conversionOptimizerEligibility: IConversionOptimizerEligibility;
26+
readonly conversionOptimizerEligibility: IConversionOptimizerEligibility;
2727
adServingOptimizationStatus: AdServingOptimizationStatus;
2828
frequencyCap: IFrequencyCap;
29-
settings: ISetting[];
29+
// TODO: add more settings
30+
settings: IGeoTargetTypeSetting | any;
3031
advertisingChannelType: AdvertisingChannelType;
3132
advertisingChannelSubType: AdvertisingChannelSubType;
3233
networkSetting: INetworkSetting;
@@ -39,7 +40,7 @@ interface ICampaignRaw {
3940
finalUrlSuffix: string;
4041
urlCustomParameters: ICustomParameters;
4142

42-
// TODO
43+
// TODO: add types
4344
vanityPharma: any;
4445
universalAppCampaignInfo: any;
4546
selectiveOptimization: any;
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { IOperation } from '../../../types/adwords';
22
import { ICampaignLabel } from './CampaignLabel';
33

4-
export interface ICampaignLabelOperation extends IOperation {
4+
export interface ICampaignLabelOperation extends IOperation<'CampaignLabelOperation'> {
55
operand: ICampaignLabel;
66
}

0 commit comments

Comments
 (0)