Skip to content

Commit 4be0065

Browse files
committed
auxia experiment: move functions to lib and give them tests
1 parent cc7ac4d commit 4be0065

File tree

3 files changed

+405
-218
lines changed

3 files changed

+405
-218
lines changed

src/server/api/auxiaProxyRouter.ts

Lines changed: 9 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,21 @@ import express, { Router } from 'express';
22
import { isProd } from '../lib/env';
33
import { getSsmValue } from '../utils/ssm';
44
import { bodyContainsAllFields } from '../middleware';
5-
6-
// --------------------------------
7-
// Basic Types
8-
// --------------------------------
5+
import {
6+
buildGetTreatmentsRequestPayload,
7+
guDefaultGateGetTreatmentsResponseData,
8+
AuxiaAPIGetTreatmentsResponseData,
9+
isValidContentType,
10+
isValidSection,
11+
isValidTagIdCollection,
12+
buildAuxiaProxyGetTreatmentsResponseData,
13+
} from '../signin-gate/lib';
914

1015
export interface AuxiaRouterConfig {
1116
apiKey: string;
1217
projectId: string;
1318
}
1419

15-
// --------------------------------
16-
// Auxia API Types
17-
// --------------------------------
18-
19-
interface AuxiaAPIContextualAttributeString {
20-
key: string;
21-
stringValue: string;
22-
}
23-
24-
interface AuxiaAPIContextualAttributeBoolean {
25-
key: string;
26-
boolValue: boolean;
27-
}
28-
29-
interface AuxiaAPIContextualAttributeInteger {
30-
key: string;
31-
integerValue: number;
32-
}
33-
34-
type AuxiaAPIGenericContexualAttribute =
35-
| AuxiaAPIContextualAttributeString
36-
| AuxiaAPIContextualAttributeBoolean
37-
| AuxiaAPIContextualAttributeInteger;
38-
39-
interface AuxiaAPISurface {
40-
surface: string;
41-
maximumTreatmentCount: number;
42-
}
43-
44-
interface AuxiaAPIUserTreatment {
45-
treatmentId: string;
46-
treatmentTrackingId: string;
47-
rank: string;
48-
contentLanguageCode: string;
49-
treatmentContent: string;
50-
treatmentType: string;
51-
surface: string;
52-
}
53-
54-
interface AuxiaAPIGetTreatmentsRequestPayload {
55-
projectId: string;
56-
userId: string;
57-
contextualAttributes: AuxiaAPIGenericContexualAttribute[];
58-
surfaces: AuxiaAPISurface[];
59-
languageCode: string;
60-
}
61-
6220
interface AuxiaAPILogTreatmentInteractionRequestPayload {
6321
projectId: string;
6422
userId: string;
@@ -70,24 +28,6 @@ interface AuxiaAPILogTreatmentInteractionRequestPayload {
7028
actionName: string;
7129
}
7230

73-
interface AuxiaAPIGetTreatmentsResponseData {
74-
responseId: string;
75-
userTreatments: AuxiaAPIUserTreatment[];
76-
}
77-
78-
// --------------------------------
79-
// Proxy Types
80-
// --------------------------------
81-
82-
interface AuxiaProxyGetTreatmentsResponseData {
83-
responseId: string;
84-
userTreatment?: AuxiaAPIUserTreatment;
85-
}
86-
87-
// --------------------------------
88-
// Proxy Common Functions
89-
// --------------------------------
90-
9131
export const getAuxiaRouterConfig = async (): Promise<AuxiaRouterConfig> => {
9232
const stage = isProd ? 'PROD' : 'CODE';
9333

@@ -107,138 +47,6 @@ export const getAuxiaRouterConfig = async (): Promise<AuxiaRouterConfig> => {
10747
});
10848
};
10949

110-
// --------------------------------
111-
// Proxy Implementation GetTreatments
112-
// --------------------------------
113-
114-
const buildGetTreatmentsRequestPayload = (
115-
projectId: string,
116-
browserId: string,
117-
isSupporter: boolean,
118-
dailyArticleCount: number,
119-
articleIdentifier: string,
120-
editionId: string,
121-
): AuxiaAPIGetTreatmentsRequestPayload => {
122-
// For the moment we are hard coding the data provided in contextualAttributes and surfaces.
123-
return {
124-
projectId: projectId,
125-
userId: browserId, // In our case the userId is the browserId.
126-
contextualAttributes: [
127-
{
128-
key: 'is_supporter',
129-
boolValue: isSupporter,
130-
},
131-
{
132-
key: 'daily_article_count',
133-
integerValue: dailyArticleCount,
134-
},
135-
{
136-
key: 'article_identifier',
137-
stringValue: articleIdentifier,
138-
},
139-
{
140-
key: 'edition',
141-
stringValue: editionId,
142-
},
143-
],
144-
surfaces: [
145-
{
146-
surface: 'ARTICLE_PAGE',
147-
maximumTreatmentCount: 1,
148-
},
149-
],
150-
languageCode: 'en-GB',
151-
};
152-
};
153-
154-
const guDefaultShouldShowTheGate = (daily_article_count: number): boolean => {
155-
// We show the GU gate every 10 pageviews
156-
return daily_article_count % 10 == 0;
157-
};
158-
159-
const guDefaultGateGetTreatmentsResponseData = (
160-
daily_article_count: number,
161-
gateDismissCount: number,
162-
): AuxiaAPIGetTreatmentsResponseData => {
163-
// This function is called in the case of non consenting users, which is detected by the absence of the browserId.
164-
165-
const responseId = ''; // This value is not important, it is not used by the client.
166-
167-
// First we enforce the GU policy of not showing the gate if the user has dismissed it more than 5 times.
168-
// (We do not want users to have to dismiss the gate 6 times)
169-
170-
if (gateDismissCount > 5) {
171-
return {
172-
responseId,
173-
userTreatments: [],
174-
};
175-
}
176-
177-
// Then to prevent showing the gate too many times, we only show the gate every 10 pages views
178-
179-
if (!guDefaultShouldShowTheGate(daily_article_count)) {
180-
return {
181-
responseId,
182-
userTreatments: [],
183-
};
184-
}
185-
186-
// We are now clear to show the default gu gate.
187-
188-
const title = 'Register: it’s quick and easy';
189-
const subtitle = 'It’s still free to read – this is not a paywall';
190-
const body =
191-
'We’re committed to keeping our quality reporting open. By registering and providing us with insight into your preferences, you’re helping us to engage with you more deeply, and that allows us to keep our journalism free for all.';
192-
const secondCtaName = 'I’ll do it later';
193-
const treatmentContent = {
194-
title,
195-
subtitle,
196-
body,
197-
first_cta_name: 'Sign in',
198-
first_cta_link: 'https://profile.theguardian.com/signin?',
199-
second_cta_name: secondCtaName,
200-
second_cta_link: 'https://profile.theguardian.com/signin?',
201-
};
202-
const treatmentContentEncoded = JSON.stringify(treatmentContent);
203-
const userTreatment: AuxiaAPIUserTreatment = {
204-
treatmentId: 'default-treatment-id',
205-
treatmentTrackingId: 'default-treatment-tracking-id',
206-
rank: '1',
207-
contentLanguageCode: 'en-GB',
208-
treatmentContent: treatmentContentEncoded,
209-
treatmentType: 'DISMISSABLE_SIGN_IN_GATE',
210-
surface: 'ARTICLE_PAGE',
211-
};
212-
const data: AuxiaAPIGetTreatmentsResponseData = {
213-
responseId,
214-
userTreatments: [userTreatment],
215-
};
216-
return data;
217-
};
218-
219-
const isValidContentType = (contentType: string): boolean => {
220-
const validTypes = ['Article'];
221-
return validTypes.includes(contentType);
222-
};
223-
224-
const isValidSection = (sectionId: string): boolean => {
225-
const invalidSections = [
226-
'about',
227-
'info',
228-
'membership',
229-
'help',
230-
'guardian-live-australia',
231-
'gnm-archive',
232-
];
233-
return !invalidSections.some((section: string): boolean => sectionId === section);
234-
};
235-
236-
const isValidTagIdCollection = (tagIds: string[]): boolean => {
237-
const invalidTagIds = ['info/newsletter-sign-up'];
238-
// Check that no tagId is in the invalidTagIds list.
239-
return !tagIds.some((tagId: string): boolean => invalidTagIds.includes(tagId));
240-
};
241-
24250
const callGetTreatments = async (
24351
apiKey: string,
24452
projectId: string,
@@ -316,23 +124,6 @@ const callGetTreatments = async (
316124
}
317125
};
318126

319-
const buildAuxiaProxyGetTreatmentsResponseData = (
320-
auxiaData: AuxiaAPIGetTreatmentsResponseData,
321-
): AuxiaProxyGetTreatmentsResponseData | undefined => {
322-
// Note the small difference between AuxiaAPIResponseData and AuxiaProxyResponseData
323-
// In the case of AuxiaProxyResponseData, we have an optional userTreatment field, instead of an array of userTreatments.
324-
// This is to reflect the what the client expect semantically.
325-
326-
return {
327-
responseId: auxiaData.responseId,
328-
userTreatment: auxiaData.userTreatments[0],
329-
};
330-
};
331-
332-
// --------------------------------
333-
// LogTreatmentInteraction Implementation
334-
// --------------------------------
335-
336127
const buildLogTreatmentInteractionRequestPayload = (
337128
projectId: string,
338129
browserId: string,

0 commit comments

Comments
 (0)