Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Ajoute le tracking pour la campagne apprentissage #3363

Merged
merged 32 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
91427ee
wip: Commit pour review app
Mintoo200 Oct 9, 2024
7421fac
style: Fix lint
Mintoo200 Oct 9, 2024
c0255d5
wip: First draft TikTok
Mintoo200 Oct 10, 2024
6e1b8be
wip: Fix pagename pas reset quand on change de page
Mintoo200 Oct 11, 2024
003015b
wip: Ajoute Azerion
Mintoo200 Oct 11, 2024
5b1a97b
style: lint
Mintoo200 Oct 11, 2024
ab6d797
fix: Fix csp
Mintoo200 Oct 11, 2024
a062603
fix: Fix pixel présent au changement de page
Mintoo200 Oct 11, 2024
e1b1473
fix: Ajoute les CSP
Mintoo200 Oct 11, 2024
9eaee56
wip: Ajoute la régie Xandr pour Amnet
Mintoo200 Oct 11, 2024
2c9602d
wip: migrate from wandr to custom service for Amnet marketing service
Oct 14, 2024
9de8973
wip: remove Amnet pixel since it's a duplicate with page_view event
Oct 14, 2024
5b44e4e
wip: add adsrvr script to amnet marketing service
Oct 14, 2024
77d9e12
wip: add zemanta script to amnet marketing service
Oct 14, 2024
c86d716
wip: move from zemanta script to pixel tracking
Oct 14, 2024
b2d6f8d
wip: create meta marketing service
Oct 14, 2024
eb8393d
wip: Renomme le service Amnet
Mintoo200 Oct 11, 2024
a693b92
fix: Fix format CSP
Mintoo200 Oct 15, 2024
5427ec7
wip: Skip les tests qui manque d'une dépendance pour pouvoir build
Mintoo200 Oct 15, 2024
f95f784
wip: Extrait les 3 scripts Amnet dans des services tarteaucitron
Mintoo200 Oct 16, 2024
4393e23
wip: Ajoute les cookies utilisés par les différents services
Mintoo200 Oct 16, 2024
3038188
wip: Fix les CSP
Mintoo200 Oct 16, 2024
1d05ab3
wip: "Fix" le tracker Meta
Mintoo200 Oct 16, 2024
2c446d1
wip: Fix les cookies qui n'étaient pas supprimés pour TikTok et Meta
Mintoo200 Oct 16, 2024
9fadba8
wip: update Zemanta cookie list
Oct 17, 2024
a61c398
wip: update SeedTag script for tracking
Oct 17, 2024
c9c6347
wip: move from meta script to meta pixel img
Oct 18, 2024
1ab1bd7
tests: Fix les dépendances des tests
Mintoo200 Oct 18, 2024
6ad3a5f
config: Fix package-lock
Mintoo200 Oct 18, 2024
47e549a
refactor: Extrait la gestion du re-trigger dans le cookiesService
Mintoo200 Oct 18, 2024
37c5de5
wip: Update le wording
Mintoo200 Oct 21, 2024
a80f55e
style: fix lint
Mintoo200 Oct 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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