Skip to content
This repository has been archived by the owner on May 8, 2024. It is now read-only.

Commit

Permalink
Added Google Analytics/reCAPTCHA services complete opt-out
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianLeChat committed Aug 6, 2023
1 parent b6b10e4 commit bf60b19
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 32 deletions.
20 changes: 15 additions & 5 deletions .env
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
# NextJS parameters
NEXT_PUBLIC_ENV=development

# Website public data
NEXT_PUBLIC_URL=http://localhost:3000/
NEXT_PUBLIC_TAGS=serious, game, construction, educational
NEXT_PUBLIC_TITLE=Domego
NEXT_PUBLIC_AUTHOR=Florian Trayon
NEXT_PUBLIC_BANNER=https://opengraph.githubassets.com/9694355db18d9b48687cf1656a2f5c4921fa5a98aee3fed92f93da4dd2bfead2/FlorianLeChat/Domego
NEXT_PUBLIC_BANNER=https://opengraph.githubassets.com/master/FlorianLeChat/Domego
NEXT_PUBLIC_TWITTER=@FlorianTrayon
NEXT_PUBLIC_DESCRIPTION=Domego is a serious educational game in which each player takes the role of an actor in a construction operation.
NEXT_PUBLIC_CAPTCHA_PUBLIC_KEY=
NEXT_PUBLIC_ANALYTICS_IDENTIFIER=

# Google Analytics and reCAPTCHA keys
NEXT_PUBLIC_RECAPTCHA_ENABLED=false
NEXT_PUBLIC_RECAPTCHA_PUBLIC_KEY=6Lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

NEXT_PUBLIC_ANALYTICS_ENABLED=false
NEXT_PUBLIC_ANALYTICS_TAG=G-XXXXXXXXXX

RECAPTCHA_SECRET_KEY=6Lxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# MongoDB credentials
MONGODB_HOST=localhost
MONGODB_PORT=27017
MONGODB_DATABASE=domego
MONGODB_USERNAME=username
MONGODB_PASSWORD=password
CAPTCHA_SECRET_KEY=
MONGODB_PASSWORD=password
33 changes: 21 additions & 12 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ function Domego( { Component, pageProps }: AppProps )
const recaptchaUrl = new URL( "https://www.google.com/recaptcha/api.js" );
const favicons = `${ basePath }/assets/favicons`;

analyticsUrl.searchParams.append( "id", process.env.NEXT_PUBLIC_ANALYTICS_IDENTIFIER ?? "" );
recaptchaUrl.searchParams.append( "render", process.env.NEXT_PUBLIC_CAPTCHA_PUBLIC_KEY ?? "" );
analyticsUrl.searchParams.append( "id", process.env.NEXT_PUBLIC_ANALYTICS_TAG ?? "" );
recaptchaUrl.searchParams.append( "render", process.env.NEXT_PUBLIC_RECAPTCHA_PUBLIC_KEY ?? "" );

// Déclaration des variables d'état.
const [ analytics, setAnalytics ] = useState( false );
const [ recaptcha, setRecaptcha ] = useState( false );

// Création du socket de communication avec le serveur.
// Source : https://github.com/vercel/next.js/discussions/15341
Expand Down Expand Up @@ -119,14 +120,20 @@ function Domego( { Component, pageProps }: AppProps )
},

// Exécution des actions de consentement.
onConsent: ( { cookie } ) => (
cookie.categories.find( ( category: string ) => category === "analytics" ) && setAnalytics( true )
),

// Exécution des actions de changement.
onChange: ( { cookie } ) => (
cookie.categories.find( ( category: string ) => category === "analytics" ) && setAnalytics( true )
)
onConsent: ( { cookie } ) =>
{
cookie.categories.forEach( ( category: string ) =>
{
if ( category === "analytics" )
{
setAnalytics( process.env.NEXT_PUBLIC_ANALYTICS_ENABLED === "true" );
}
else if ( category === "security" )
{
setRecaptcha( process.env.NEXT_PUBLIC_RECAPTCHA_ENABLED === "true" );
}
} );
}
}
);
}, [ basePath ] );
Expand Down Expand Up @@ -161,7 +168,6 @@ function Domego( { Component, pageProps }: AppProps )
{analytics && (
<>
<Script src={analyticsUrl.href} strategy="lazyOnload" />
<Script src={recaptchaUrl.href} strategy="lazyOnload" />
<Script id="google-analytics" strategy="lazyOnload">
{`
window.dataLayer = window.dataLayer || [];
Expand All @@ -172,12 +178,15 @@ function Domego( { Component, pageProps }: AppProps )
}
gtag( "js", new Date() );
gtag( "config", "${ process.env.NEXT_PUBLIC_ANALYTICS_IDENTIFIER ?? "" }" );
gtag( "config", "${ process.env.NEXT_PUBLIC_ANALYTICS_TAG ?? "" }" );
`}
</Script>
</>
)}

{/* Google reCAPTCHA */}
{recaptcha && <Script src={recaptchaUrl.href} strategy="lazyOnload" />}

{/* Avertissement page sans JavaScript */}
<noscript>
<h1>Your browser does not support or refuses to load JavaScript.</h1>
Expand Down
28 changes: 17 additions & 11 deletions pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default function GameHome()
// Google reCAPTCHA pour déterminer si l'utilisateur est un humain.
const Swal = ( await import( "sweetalert2" ) ).default;

if ( process.env.NEXT_PUBLIC_CAPTCHA_PUBLIC_KEY && process.env.NEXT_PUBLIC_ENV === "production" )
if ( process.env.NEXT_PUBLIC_RECAPTCHA_ENABLED === "true" )
{
await Swal.fire( {
icon: "info",
Expand Down Expand Up @@ -79,7 +79,7 @@ export default function GameHome()
{
// Récupération et vérification du jeton d'authentification généré
// par l'API de Google reCAPTCHA.
const key = process.env.NEXT_PUBLIC_CAPTCHA_PUBLIC_KEY ?? "";
const key = process.env.NEXT_PUBLIC_RECAPTCHA_PUBLIC_KEY ?? "";
const token = await window.grecaptcha.execute( key, { action: "create" } );

socket?.emit( "GameRecaptcha", token, ( icon: SweetAlertIcon, title: string, message: string ) =>
Expand Down Expand Up @@ -259,15 +259,21 @@ export default function GameHome()

{/* Avertissement de Google reCAPTCHA */}
<small>
<Trans
i18nKey="pages.index.google_recaptcha"
components={{
a1: <a href="https://policies.google.com/privacy">...</a>,
a2: <a href="https://policies.google.com/terms">...</a>
}}
/>

<br />
{
( process.env.NEXT_PUBLIC_RECAPTCHA_ENABLED === "true" ) && (
<>
<Trans
i18nKey="pages.index.google_recaptcha"
components={{
a1: <a href="https://policies.google.com/privacy">...</a>,
a2: <a href="https://policies.google.com/terms">...</a>
}}
/>

<br />
</>
)
}

<Trans
i18nKey="pages.index.cookies_preferences"
Expand Down
7 changes: 3 additions & 4 deletions routes/recaptcha.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ export function Recaptcha( _io: Server, socket: Socket )
{
socket.on( "GameRecaptcha", async ( token, callback ) =>
{
// On vérifie d'abord si la clé secrète de l'API de Google reCAPTCHA
// a été définie ou non.
if ( !process.env.CAPTCHA_SECRET_KEY || process.env.NEXT_PUBLIC_ENV === "development" )
// On vérifie d'abord si le service est activé ou non.
if ( process.env.NEXT_PUBLIC_RECAPTCHA_ENABLED === "false" )
{
callback( "success", "🤖", "🤖" );
return;
Expand All @@ -27,7 +26,7 @@ export function Recaptcha( _io: Server, socket: Socket )
// On effectue alors une requête à l'API de Google reCAPTCHA
// afin de vérifier si le jeton d'authentification envoyé par le client
// est valide ou non.
const secret = process.env.CAPTCHA_SECRET_KEY;
const secret = process.env.RECAPTCHA_SECRET_KEY;
const endpoint = `https://www.google.com/recaptcha/api/siteverify?secret=${ secret }&response=${ token }`;
const response = await fetch( endpoint );

Expand Down

0 comments on commit bf60b19

Please sign in to comment.