@@ -2,92 +2,22 @@ import express, { Router } from 'express';
22import { isProd } from '../lib/env' ;
33import { getSsmValue } from '../utils/ssm' ;
44import { 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+ buildLogTreatmentInteractionRequestPayload ,
14+ } from '../signin-gate/lib' ;
915
1016export interface AuxiaRouterConfig {
1117 apiKey : string ;
1218 projectId : string ;
1319}
1420
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-
62- interface AuxiaAPILogTreatmentInteractionRequestPayload {
63- projectId : string ;
64- userId : string ;
65- treatmentTrackingId : string ;
66- treatmentId : string ;
67- surface : string ;
68- interactionType : string ;
69- interactionTimeMicros : number ;
70- actionName : string ;
71- }
72-
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-
9121export const getAuxiaRouterConfig = async ( ) : Promise < AuxiaRouterConfig > => {
9222 const stage = isProd ? 'PROD' : 'CODE' ;
9323
@@ -107,138 +37,6 @@ export const getAuxiaRouterConfig = async (): Promise<AuxiaRouterConfig> => {
10737 } ) ;
10838} ;
10939
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-
24240const callGetTreatments = async (
24341 apiKey : string ,
24442 projectId : string ,
@@ -316,45 +114,6 @@ const callGetTreatments = async (
316114 }
317115} ;
318116
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-
336- const buildLogTreatmentInteractionRequestPayload = (
337- projectId : string ,
338- browserId : string ,
339- treatmentTrackingId : string ,
340- treatmentId : string ,
341- surface : string ,
342- interactionType : string ,
343- interactionTimeMicros : number ,
344- actionName : string ,
345- ) : AuxiaAPILogTreatmentInteractionRequestPayload => {
346- return {
347- projectId : projectId ,
348- userId : browserId , // In our case the userId is the browserId.
349- treatmentTrackingId,
350- treatmentId,
351- surface,
352- interactionType,
353- interactionTimeMicros,
354- actionName,
355- } ;
356- } ;
357-
358117const callLogTreatmentInteration = async (
359118 apiKey : string ,
360119 projectId : string ,
0 commit comments