# Profiling Consent Profiling consent allows users to opt in/out of personalized experiences. The feature is controlled by the `ENABLE_PROFILE_CONSENT` environment variable. ## User Journey 1. **Signup**: Optional consent checkbox in registration form 2. **My Pages Modal**: Prompt shown on first visit (if no decision made) 3. **Banner**: Shown on overview page if modal was dismissed without deciding 4. **Profile Settings**: Dedicated page at `/profile/consent` to update consent at any time ## Components ### Modal (`Modal/`) Full-page modal shown when a user first visits a My Pages route. - Rendered in `app/[lang]/(live)/(protected)/my-pages/layout.tsx` - Only shows if user hasn't made a consent decision (`profilingConsent` is `undefined`) - Uses `memberKey` (from `membershipNumber` or `profileId`) for dismissal tracking - Close via "X" button only (no overlay click or ESC key) - Accept/Decline buttons update consent via API **Sub-components:** - `Modal/BenefitCards/` — Cards showcasing personalization benefits - `Modal/ReadOnly.tsx` — Informational version without action buttons (used in signup) ### Banner (`Banner/`) Shown on the account overview page when consent is pending. - Server component that checks `userHasConsent()` before rendering - CTA button dispatches `profiling-consent:open` event to reopen the modal - Added to overview via Contentstack Dynamic Content block ### Alert (`Alert/`) Feedback alert shown after consent actions in My Pages. - `ProfilingConsentAlertProvider` — Context provider in My Pages layout - Shows success/error states after accepting/declining consent - Success alert includes link to edit preferences ### Consent Form (`components/Forms/ProfilingConsent/`) Dedicated form on `/profile/consent` page for managing consent. - Radio button selection for Accept/Decline - Shows current consent status - Redirects to profile after saving - Includes accordion with privacy information ### Signup Integration The signup form (`components/Forms/Signup/index.tsx`) includes: - Checkbox to opt-in during registration - "Read more" link that opens `Modal/ReadOnly.tsx` ### Profile Settings `PersonalizationSlot` in `components/MyPages/Profile/CommunicationSettings/` provides a link to the consent management page. ### Accordion (`Accordion/`) Expandable section with privacy and personalization details. Used in both the modal and consent form. ## API ### tRPC Mutations - `trpc.user.profilingConsent.update` — Update user's consent preference - `trpc.user.profilingConsentPromptDate.update` — Record when user was prompted ### tRPC Queries - `trpc.contentstack.profilingConsent.get` — Fetch modal/banner content from CMS ## Hooks - `useUpdateProfilingConsent` (`hooks/useUpdateProfilingConsent.ts`) — Handles consent update mutation with alert feedback via `ProfilingConsentAlertProvider` ## Local Storage Modal dismissal is tracked per-member to control auto-open behavior: - Key: `profiling-consent:dismissed:` - Set when modal is closed via header close button - Does not reflect Accept/Decline (those are stored via API) ## Utilities Located at `utils/profilingConsent.ts`: - `storageKey(memberKey)` — Generate storage key - `readDismissed(memberKey)` — Check if modal was dismissed - `setDismissed(memberKey)` — Mark modal as dismissed - `clearDismissed(memberKey)` — Clear dismissal flag - `profilingConsentOpenEvent` — CustomEvent name for opening modal - `requestOpen()` — Dispatch event to open modal ## Testing Re-show modal after dismissing: ```js localStorage.removeItem("profiling-consent:dismissed:") // Refresh the page ``` Open modal programmatically: ```js window.dispatchEvent(new CustomEvent("profiling-consent:open")) ``` Replace `` with the actual `membershipNumber` or `profileId`. ## Contentstack Setup Required content for the feature: 1. **Profiling Consent (config)** - Config needs to be created and published in each language 2. **/consent (account page)** - Page needs to be created and published in each language 3. **/overview (account page)** - Add Dynamic content block: "Profiling Consent Banner" - Re-publish the page for each language