Skip to content

Commit

Permalink
feat: Ajoute le tracking pour la campagne apprentissage (#3363)
Browse files Browse the repository at this point in the history
* wip: Commit pour review app

* style: Fix lint

* wip: First draft TikTok

* wip: Fix pagename pas reset quand on change de page

* wip: Ajoute Azerion

* style: lint

* fix: Fix csp

* fix: Fix pixel présent au changement de page

* fix: Ajoute les CSP

* wip: Ajoute la régie Xandr pour Amnet

* wip: migrate from wandr to custom service for Amnet marketing service

* wip: remove Amnet pixel since it's a duplicate with page_view event

* wip: add adsrvr script to amnet marketing service

* wip: add zemanta script to amnet marketing service

Warning: page view event is still fired after choisir-apprentissage page exit

* wip: move from zemanta script to pixel tracking

* wip: create meta marketing service

* wip: Renomme le service Amnet

* fix: Fix format CSP

* wip: Skip les tests qui manque d'une dépendance pour pouvoir build

* wip: Extrait les 3 scripts Amnet dans des services tarteaucitron

* wip: Ajoute les cookies utilisés par les différents services

* wip: Fix les CSP

* wip: "Fix" le tracker Meta

* wip: Fix les cookies qui n'étaient pas supprimés pour TikTok et Meta

* wip: update Zemanta cookie list

* wip: update SeedTag script for tracking

* wip: move from meta script to meta pixel img

* tests: Fix les dépendances des tests

* config: Fix package-lock

* refactor: Extrait la gestion du re-trigger dans le cookiesService

* wip: Update le wording

* style: fix lint

---------

Co-authored-by: Florian Leroy <florian.leroy@octo.com>
  • Loading branch information
Mintoo200 and Florian Leroy authored Oct 21, 2024
1 parent 4dbd88a commit 62a2581
Show file tree
Hide file tree
Showing 22 changed files with 1,750 additions and 3,512 deletions.
2 changes: 2 additions & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// @ts-nocheck

import type { StorybookConfig } from "@storybook/nextjs";
const path = require('path');

Expand Down
8 changes: 5 additions & 3 deletions config/headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ const LOCAL_MODE_HEADERS = [];
const STRAPI_MEDIA_HOST = new URL(process.env.STRAPI_MEDIA_URL).hostname;
const TRUSTED_SOURCES = '*.fabrique.social.gouv.fr *.meilisearch.io/multi-search *.meilisearch.com/multi-search 1j1s-front.osc-fr1.scalingo.io *.1jeune1solution.gouv.fr';
const ANALYTICS_SOURCES = `${process.env.NEXT_PUBLIC_ANALYTICS_DOMAIN} ${process.env.NEXT_PUBLIC_ANALYTICS_MATOMO_HOST}`;
// FIXME (GAFI 16-10-2024): Si on passait par un Record<CSPKeys, string[]>, ça pourrait nous éviter les typos et améliorer la lisibilité
const contentSecurityPolicy = `
default-src 'self' ${TRUSTED_SOURCES};
script-src 'self' ${ANALYTICS_SOURCES} https://*.adform.net;
img-src 'self' *.google.com data: ${STRAPI_MEDIA_HOST} ${ANALYTICS_SOURCES} img.youtube.com jedonnemonavis.numerique.gouv.fr;
script-src 'self' ${ANALYTICS_SOURCES} https://*.adform.net www.googletagmanager.com analytics.tiktok.com *.adnxs.com *.adsrvr.org *.facebook.com *.facebook.net;
img-src 'self' *.google.com data: ${STRAPI_MEDIA_HOST} ${ANALYTICS_SOURCES} img.youtube.com jedonnemonavis.numerique.gouv.fr *.adnxs.com *.adsrvr.org *.doubleclick.net p1.zemanta.com *.facebook.com;
style-src 'self' 'unsafe-inline' ${ANALYTICS_SOURCES};
frame-ancestors 'none';
frame-src 'self' *.apprentissage.beta.gouv.fr immersion-facile.beta.gouv.fr deposer-offre.www.1jeune1solution.gouv.fr *.youtube-nocookie.com simulateur-alternance.1jeune1solution.gouv.fr https://*.adform.net mes-aides.francetravail.fr;
frame-src 'self' *.apprentissage.beta.gouv.fr immersion-facile.beta.gouv.fr deposer-offre.www.1jeune1solution.gouv.fr *.youtube-nocookie.com simulateur-alternance.1jeune1solution.gouv.fr https://*.adform.net mes-aides.francetravail.fr *.doubleclick.net *.adsrvr.org;
form-action 'self';
base-uri 'none';
connect-src 'self' ${TRUSTED_SOURCES} analytics.tiktok.com *.facebook.com *.adnxs.com;
`;

const SECURITY_MODE_HEADERS = [{
Expand Down
2 changes: 1 addition & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
4,759 changes: 1,278 additions & 3,481 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion public/scripts/tarteaucitron/lang/tarteaucitron.fr.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 25 additions & 8 deletions public/scripts/tarteaucitron/tarteaucitron.services.js
Original file line number Diff line number Diff line change
Expand Up @@ -1278,10 +1278,10 @@ tarteaucitron.services.xandr = {
});
},
key: 'xandr',
name: 'Xandr (Universal)',
name: 'Amnet - Xandr',
needConsent: true,
type: 'ads',
uri: 'https://www.xandr.com/privacy/cookie-policy/',
uri: 'https://support.google.com/displayvideo/topic/3528231?hl=en&ref_topic=9059505&sjid=9933903973918710720-EU',
};

// xandr segment
Expand Down Expand Up @@ -6005,11 +6005,28 @@ tarteaucitron.services.outbrain = {
cookies: [],
js: function () {
'use strict';

tarteaucitron.addScript('https://widgets.outbrain.com/outbrain.js');
if (tarteaucitron.user.zemTagId == null) {
return;
}
if (window.zemApi) {
return;
}
var api = window.zemApi = function() {
api.dispatch ? api.dispatch.apply(api, arguments) : api.queue.push(arguments);
};
api.version = '1.0';
api.loaded = true;
api.marketerId = [tarteaucitron.user.zemTagId];
document.addEventListener('navigate', () => {
api.marketerId = []
})
api.queue = [];
tarteaucitron.addScript('//js-tag.zemanta.com/zcpt.js', undefined,function() {
window.zemApi('track', 'PAGE_VIEW');
}, undefined, 'defer', 'true');
},
key: 'outbrain',
name: 'Outbrain',
name: 'Amnet - Outbrain',
needConsent: true,
type: 'ads',
uri: 'https://www.outbrain.com/fr/advertisers/guidelines/',
Expand Down Expand Up @@ -6353,7 +6370,7 @@ tarteaucitron.services.weborama = {

// tiktok
tarteaucitron.services.tiktok = {
cookies: [],
cookies: ['_tt_enable_cookie', '_ttp'],
js: function () {
'use strict';

Expand All @@ -6370,8 +6387,8 @@ tarteaucitron.services.tiktok = {
key: 'tiktok',
name: 'Tiktok',
needConsent: true,
type: 'analytic',
uri: 'https://www.tiktok.com/legal/tiktok-website-cookies-policy',
type: 'ads',
uri: 'https://www.tiktok.com/legal/page/global/cookie-policy/fr',
};

// Klaviyo
Expand Down
20 changes: 20 additions & 0 deletions src/client/dependencies.container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ import { BffLocalisationService } from '~/client/services/localisation/bff.local
import { LocalisationService } from '~/client/services/localisation/localisation.service';
import { LoggerService } from '~/client/services/logger.service';
import { AdformMarketingService } from '~/client/services/marketing/adform/adform.marketing.service';
import AmnetMarketingService from '~/client/services/marketing/amnet/amnet.marketing.service';
import AzerionMarketingService from '~/client/services/marketing/azerion/azerion.marketing.service';
import { MarketingService } from '~/client/services/marketing/marketing.service';
import MetaMarketingService from '~/client/services/marketing/meta/meta.marketing.service';
import { NullMarketingService } from '~/client/services/marketing/null/null.marketing.service';
import SeedtagMarketingService from '~/client/services/marketing/seedtag/seedtag.marketing.service';
import TiktokMarketingService from '~/client/services/marketing/TikTok/tiktok.marketing.service';
import { BffAlternanceMetierService } from '~/client/services/metiers/bff.alternance.metier.service';
import { MetierService } from '~/client/services/metiers/metier.service';
import { BffMissionEngagementService } from '~/client/services/missionEngagement/bff.missionEngagement.service';
Expand Down Expand Up @@ -90,6 +95,11 @@ export type Dependencies = {
stageDeposerOffreEtape3PersistenceService: StageDeposerOffreEtape3PersistenceService
localStorageService: StorageService
sessionStorageService: StorageService
seedtagService: MarketingService
tiktokService: MarketingService
azerionService: MarketingService
amnetService: MarketingService
metaService: MarketingService
}

class DependencyInitException extends Error {
Expand Down Expand Up @@ -117,6 +127,11 @@ export default function dependenciesContainer(sessionId?: string): Dependencies
const emploiEuropeService = new BffEmploiEuropeService(httpClientService);
const stageService = new BffStageService(httpClientService);
const cookiesService = getCookieService();
const seedtagService = new SeedtagMarketingService(cookiesService);
const tiktokService = new TiktokMarketingService(cookiesService);
const azerionService = new AzerionMarketingService(cookiesService);
const amnetService = new AmnetMarketingService(cookiesService);
const metaService = new MetaMarketingService(cookiesService);
const marketingService = process.env.NEXT_PUBLIC_CAMPAGNE_ADFORM_FEATURE === '1'
? new AdformMarketingService(cookiesService)
: new NullMarketingService();
Expand Down Expand Up @@ -165,7 +180,9 @@ export default function dependenciesContainer(sessionId?: string): Dependencies
getStorageServiceWithFallback(localStorageService, new NullStorageService()));

return {
amnetService,
analyticsService,
azerionService,
cookiesService,
dateService,
demandeDeContactService,
Expand All @@ -174,16 +191,19 @@ export default function dependenciesContainer(sessionId?: string): Dependencies
localStorageService,
localisationService,
marketingService,
metaService,
metierLbaService,
metierStage3eEt2deService,
missionEngagementService,
rechercheClientService,
seedtagService,
sessionStorageService,
stage3eEt2deService,
stageDeposerOffreEtape1PersistenceService,
stageDeposerOffreEtape2PersistenceService,
stageDeposerOffreEtape3PersistenceService,
stageService,
tiktokService,
youtubeService,
établissementAccompagnementService,
};
Expand Down
1 change: 1 addition & 0 deletions src/client/services/cookies/cookies.service.fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export function aCookiesService(override?: Partial<CookiesService>): CookiesServ
allowService: jest.fn(),
isServiceAllowed: jest.fn(() => true),
openPanel: jest.fn(),
triggerJobs: jest.fn(),
...override,
};
}
2 changes: 2 additions & 0 deletions src/client/services/cookies/cookies.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ export interface CookiesService {
allowService(nom: string): void;

openPanel(): void;

triggerJobs(): void;
}
4 changes: 4 additions & 0 deletions src/client/services/cookies/null/null.cookies.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,8 @@ export class NullCookiesService implements CookiesService {
openPanel(): void {
return;
}

triggerJobs(): void {
return;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export type TarteAuCitron = {
openPanel: () => void,
}
state: Record<TarteAuCitron.ServiceName, boolean>;
triggerJobsAfterAjaxCall: () => void;
}

export class TarteAuCitronCookiesService implements CookiesService {
Expand Down Expand Up @@ -58,7 +59,10 @@ export class TarteAuCitronCookiesService implements CookiesService {

addService(nom: string, config?: TarteAuCitron.ServiceConfig<unknown>): void {
if (config != undefined) {
this.tarteaucitron.services[nom] = config;
this.tarteaucitron.services[nom] = {
...(this.tarteaucitron.services[nom] ?? {}),
...config,
};
}
this.tarteaucitron.job?.push(nom);
}
Expand All @@ -84,4 +88,8 @@ export class TarteAuCitronCookiesService implements CookiesService {
openPanel(): void {
return this.tarteaucitron.userInterface.openPanel();
}

triggerJobs(): void {
return this.tarteaucitron.triggerJobsAfterAjaxCall();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export function aTarteAuCitron(override?: Partial<TarteAuCitron>): TarteAuCitron
job: undefined,
services: {},
state: {},
triggerJobsAfterAjaxCall: jest.fn(),
user: {},
userInterface: {
openPanel: jest.fn(),
Expand Down
22 changes: 22 additions & 0 deletions src/client/services/marketing/TikTok/tiktok.marketing.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { CookiesService } from '../../cookies/cookies.service';
import { MarketingService } from '../marketing.service';

export default class TiktokMarketingService implements MarketingService {
private static SERVICE_NAME = 'tiktok';
private static TIKTOK_ID = 'C90RBUPHLSUPN04HH210';

private readonly cookiesService: CookiesService;

constructor(cookiesService: CookiesService) {
this.cookiesService = cookiesService;
this.cookiesService.addService(TiktokMarketingService.SERVICE_NAME);
}

trackPage(pagename: string): void {
if (pagename === 'off') {
this.cookiesService.addUser('tiktokId', undefined);
} else {
this.cookiesService.addUser('tiktokId', TiktokMarketingService.TIKTOK_ID);
}
}
}
Loading

0 comments on commit 62a2581

Please sign in to comment.