@supaapps/mayicookies
v0.1.4
Published
Browser consent management SDK for mayicookies.
Readme
@supaapps/mayicookies
Browser SDK for mayicookies consent banners, preferences, consent recording, optional script activation, Global Privacy Control handling, and Google Consent Mode v2.
Customer Setup Flow
- Sign in to Mayicookies.
- Create a workspace.
- Add a site and whitelist the production domain.
- Configure policy text, categories, and any managed scripts.
- Copy the site-specific script tag, npm config, or GTM setup values from the site install page.
- Install Mayicookies before analytics, ads, or vendor tags run.
The site key is public and site-specific. Do not reuse a key across unrelated customer sites.
Script Tag Install
Use the hosted loader when you are not bundling npm code. The loader imports the SDK from the same CDN path, fetches the site runtime config, shows the banner when needed, writes the GTM-readable consent cookie, and exposes window.Mayicookies.
<script
async
src="https://app.mayicookies.com/mayicookies/loader.js"
data-site-key="site_REPLACE_WITH_SITE_KEY"
data-api-url="https://api.mayicookies.com/api"
data-mode="auto"
></script>Place the snippet in <head> before Google Tag Manager, gtag.js, analytics, ads, heatmaps, chat widgets, or other optional vendor scripts.
Supported loader attributes:
| Attribute | Default | Description |
| --- | --- | --- |
| data-site-key | Required | Public Mayicookies site key from the dashboard. |
| data-mayicookies-site-key | None | Namespaced alias for data-site-key. |
| data-api-url | https://api.mayicookies.com/api | Mayicookies API base URL. |
| data-mayicookies-api-url | None | Namespaced alias for data-api-url. |
| data-mode | auto | Jurisdiction mode: auto, gdpr, ccpa, cpra, vcdpa, or pipeda. |
| data-auto-block | true | Set to false to disable activation of manually blocked scripts. |
| data-google-consent-mode | true | Set to false to stop writing the GTM consent cookie and dataLayer updates. |
| data-gtm-consent-cookie-name | mayicookies_gtm_consent | Cookie read by the Mayicookies GTM template. |
| data-gtm-consent-cookie-max-age-days | 180 | Consent cookie lifetime in days. |
| data-gtm-consent-push-data-layer | true | Set to false to disable mayicookies_consent_update dataLayer events. |
| data-gtm-consent-data-layer-event | mayicookies_consent_update | Custom dataLayer event name for consent updates. |
npm Install
npm install @supaapps/mayicookiesInitialize once on every public page before optional tags run.
import { Mayicookies } from '@supaapps/mayicookies';
await Mayicookies.init({
siteKey: 'site_REPLACE_WITH_SITE_KEY',
apiUrl: 'https://api.mayicookies.com/api',
mode: 'auto',
autoBlock: true,
});Plain JavaScript:
import { Mayicookies } from '@supaapps/mayicookies';
Mayicookies.init({
siteKey: 'site_REPLACE_WITH_SITE_KEY',
apiUrl: 'https://api.mayicookies.com/api',
mode: 'auto',
autoBlock: true,
}).catch((error) => {
console.error('Mayicookies failed to initialize', error);
});Next.js or React
For Next.js App Router, initialize in a client component mounted from the root layout.
'use client';
import { useEffect } from 'react';
import { Mayicookies } from '@supaapps/mayicookies';
export function MayicookiesProvider() {
useEffect(() => {
void Mayicookies.init({
siteKey: process.env.NEXT_PUBLIC_MAYICOOKIES_SITE_KEY!,
apiUrl: process.env.NEXT_PUBLIC_MAYICOOKIES_API_URL ?? 'https://api.mayicookies.com/api',
mode: 'auto',
autoBlock: true,
});
}, []);
return null;
}import { MayicookiesProvider } from './MayicookiesProvider';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<MayicookiesProvider />
{children}
</body>
</html>
);
}For a regular React SPA, render the same provider at the top of the app before route content that can load optional tags.
Manual Script Blocking
For scripts that must wait for consent, change type to text/plain and add data-mayicookies-category.
<script
type="text/plain"
data-mayicookies-category="analytics"
src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"
></script><script type="text/plain" data-mayicookies-category="marketing">
console.log('Runs only after marketing consent is granted.');
</script>Common categories:
necessary: required site behavior, always enabled.analytics: measurement and performance tooling.marketing: ads, retargeting, conversion pixels.preferences: personalization and preference storage.sale_share: CCPA/CPRA sale or sharing choice.
The dashboard policy controls the categories available for each site.
Scripts configured in the Mayicookies dashboard are also activated by the SDK after consent. Dashboard-managed scripts support:
- External script URLs.
- Inline script code.
- Optional URL match patterns such as
/checkout/*orhttps://shop.example.com/products/*. - Script attributes such as
data-*,id,async, orcrossorigin.
The SDK only injects a dashboard-managed script when the visitor granted that script's consent category and the current URL matches its pattern.
Preferences Button
Expose a footer, privacy page, or account settings button so visitors can reopen choices.
import { Mayicookies } from '@supaapps/mayicookies';
export function CookieSettingsButton() {
return (
<button type="button" onClick={() => Mayicookies.openPreferences()}>
Cookie settings
</button>
);
}With the script loader, use:
<button type="button" onclick="window.Mayicookies?.openPreferences()">Cookie settings</button>Google Tag Manager CMP Template
Use the bundled Mayicookies CMP template for GTM containers. It calls GTM consent APIs directly, sets denied optional defaults on Consent Initialization - All Pages, reads the Mayicookies consent cookie, and listens for SDK updates through window.mayicookiesAddConsentModeListener.
Recommended setup:
- In GTM, open
Templates. - Import or create the
mayicookies CMPtemplate frompackages/gtm-template/template.tpl. - Create one tag from that template.
- Trigger it on
Consent Initialization - All Pages. - Keep
cookieNameasmayicookies_gtm_consentunless you changed the SDK cookie name. - Keep
wait_for_updateat500. - Keep
ads_data_redactionenabled. - Leave
url_passthroughdisabled unless your legal and analytics setup requires it. - Publish only after GTM Preview and Tag Assistant confirm consent order and states.
Consent Mode v2 mapping:
| Mayicookies choice | Google consent type |
| --- | --- |
| analytics=true | analytics_storage=granted |
| marketing=true | ad_storage=granted |
| marketing=true and sale_share !== false and GPC disabled | ad_user_data=granted, ad_personalization=granted |
| preferences=true | functionality_storage=granted, personalization_storage=granted |
| Always | security_storage=granted |
Before consent, optional Google storage types default to denied.
Direct gtag.js Bridge
Use this only when you do not use the GTM template.
import { Mayicookies, installGoogleConsentModeBridge } from '@supaapps/mayicookies';
await Mayicookies.init({
siteKey: 'site_REPLACE_WITH_SITE_KEY',
apiUrl: 'https://api.mayicookies.com/api',
mode: 'auto',
autoBlock: true,
});
installGoogleConsentModeBridge();installGoogleConsentModeBridge() sends a default denied optional state with wait_for_update: 500, then sends gtag('consent', 'update', ...) when preferences change.
Verify Installation
Check these on a real allowed domain:
- Network request to
/api/public/sites/{siteKey}/configreturns200. - First visit with no stored consent shows the banner.
- Accept all records a POST to
/api/public/sites/{siteKey}/consents. - Reject optional keeps optional scripts blocked.
- Category-specific scripts activate only after that category is granted.
- A
mayicookies:consent:{siteKey}localStorage entry exists after saving. - A
mayicookies_gtm_consentcookie exists when Google Consent Mode is enabled. - GTM Preview shows the Mayicookies CMP tag firing before Google or vendor tags.
- Tag Assistant shows denied optional defaults before consent and updated values after preference changes.
window.Mayicookies.openPreferences()opens the preferences modal.
Common Failures
| Symptom | Likely cause | Fix |
| --- | --- | --- |
| Banner never appears | Missing or wrong siteKey, API request failed, or snippet loads after a blocking error. | Check DevTools console and the config request URL/status. |
| Config request returns 403 | Domain is not whitelisted for the site. | Add the exact production domain in the Mayicookies site settings. |
| Consent is not recorded | API URL is wrong, network/CORS issue, or public consent endpoint is blocked. | Verify the POST to /consents and API logs. |
| Optional script runs before consent | Script was left as normal JavaScript. | Use type="text/plain" and data-mayicookies-category. |
| Optional script never runs after consent | Category key does not match the dashboard category or data-auto-block="false" is set. | Align the category key and keep auto-block enabled. |
| GTM sees no updates | CMP tag did not run on Consent Initialization or cookie names differ. | Check GTM trigger order and cookieName. |
| Google Ads personalization remains denied | Visitor opted out of sale/share or Global Privacy Control is enabled. | This is expected privacy behavior. |
Runtime API
Mayicookies.init(config)Mayicookies.getConsent()Mayicookies.setConsent(choices)Mayicookies.onConsentChange(listener)Mayicookies.getGoogleConsentModeState()Mayicookies.onGoogleConsentModeChange(listener)Mayicookies.openPreferences()Mayicookies.resetConsent()mapConsentToGoogleConsentMode(snapshot)installGoogleConsentModeBridge(options)
