Guide · June 17, 2026
Angular cookie consent for PDPL: service, guard, dynamic script loading
Guide to PDPL-compliant cookie consent for Angular: service, guard, dynamic script loading by consent, with practical examples.
Quick answer
What is angular cookie consent PDPL and why should Angular apps care?
Angular apps may not handle personal data directly in the UI, but cookies, localStorage, tag managers, chat widgets, heatmaps, analytics, or ads can trigger consent and notice obligations. With the PDPL (the Personal Data Protection Law (Law 91/2025/QH15), expected effective 01/01/2026), businesses must manage consent more clearly than under Decree 13/2023/ND-CP, especially when third parties and data transfers via scripts are involved.
For Vietnamese SMEs, common pitfalls are: a popup with only an “OK” button with no stored proof; Google/Meta scripts loading immediately on page open; or the user has refused but the app still fires tracking events. When the enforcer is the Ministry of Public Security — Department of Cybersecurity and High-Tech Crime Prevention (A05), you will need to demonstrate a compliant process under the regulations, not just “having a banner”.
How should cookie consent be designed in an Angular integration?
The best design is to treat consent as an application state, not just a popup.
You should have three layers:
- Consent service: store/read consent status, cookie categories, timestamp, notice version.
- Route or component guard: block areas that only work with consent, e.g., an internal analytics dashboard or features that require third parties.
- Dynamic script loader: inject scripts only after the user consents, instead of putting them in
index.html.
| Component | Role | PDPL notes | |
|---|---|---|---|
| ConsentService | Manage accept/decline status | Must store proof of consent | |
| CookieBannerComponent | Display choices | Clear accept/decline/customize buttons | |
| Guard | Gateflows that require consent | Do not use to “force consent”; only protect functionality | |
| ScriptLoader | Load scripts per consent | Do not load analytics/ads before consent |
How should the consent service in Angular be written?
A minimal ConsentService should read, write, and emit consent change events so other components can react.
Simple example:
export type ConsentState = 'accepted' | 'rejected' | 'custom' | null;
export interface ConsentRecord {
state: ConsentState;
updatedAt: string;
version: string;
}
@Injectable({ providedIn: 'root' })
export class ConsentService {
private key = 'cookie_consent_v1';
private consentSubject = new BehaviorSubject<ConsentRecord | null>(this.read());
consent$ = this.consentSubject.asObservable();
accept(version = '2026-01') {
const record: ConsentRecord = { state: 'accepted', updatedAt: new Date().toISOString(), version };
localStorage.setItem(this.key, JSON.stringify(record));
this.consentSubject.next(record);
}
reject(version = '2026-01') {
const record: ConsentRecord = { state: 'rejected', updatedAt: new Date().toISOString(), version };
localStorage.setItem(this.key, JSON.stringify(record));
this.consentSubject.next(record);
}
private read(): ConsentRecord | null {
const raw = localStorage.getItem(this.key);
return raw ? JSON.parse(raw) : null;
}
}
Key point: localStorage is client-side only and is not sufficient as legal evidence if you lack server-side logs. Under the regulations, you should send the consent record to your backend to keep an audit trail: user ID, anonymous ID, timestamp, banner version, truncated IP (if your internal policy allows), and the collection source.
Should a guard be used to block tracking cookies?
Yes, but for the right purpose. A guard is not to block users “because they haven’t consented,” but to block routes or features that depend on scripts/cookies that are not yet permitted.
Example: a route /analytics only for admins, but the dashboard pulls data from the Google Analytics API or an SDK according to consent. When consent is missing, the guard redirects to an explanation screen.
@Injectable({ providedIn: 'root' })
export class ConsentGuard implements CanActivate {
constructor(private consent: ConsentService, private router: Router) {}
canActivate(): boolean {
const record = this.consent['consentSubject'].value;
if (record?.state === 'accepted') return true;
this.router.navigate(['/cookie-preferences']);
return false;
}
}
Practical note: for many sites, you don’t need guards for every route. Only guard functionality that depends on tracking or third parties. More importantly, block scripts from the start.
How do you load scripts dynamically by consent in Angular?
This is the core of “angular cookie consent pdpl”: do not put a script in index.html if it may only run after consent.
A common approach is to use a script loading service:
@Injectable({ providedIn: 'root' })
export class ScriptLoaderService {
load(src: string, id: string): Promise<void> {
return new Promise((resolve, reject) => {
if (document.getElementById(id)) return resolve();
const script = document.createElement('script');
script.id = id;
script.src = src;
script.async = true;
script.onload = () => resolve();
script.onerror = () => reject(new Error(`Failed to load ${src}`));
document.body.appendChild(script);
});
}
}
Then only call it after the user has consented:
this.consent.consent$.subscribe(record => {
if (record?.state === 'accepted') {
this.scriptLoader.load('https://www.googletagmanager.com/gtag/js?id=G-XXXX', 'gtag-js');
}
});
If you use Tag Manager, chat widgets, reCAPTCHA, Hotjar, ad pixels… the principle is the same: load after consent, and provide a mechanism to disable again if the user changes their mind.
What is the implementation checklist for an Angular team?
Inventory all scripts and cookies
review `index.html`, `main.ts`, third-party SDKs, iframes, pixels, chat widgets, A/B testing.
Categorize by purpose
necessary, analytics, marketing, functionality; default off for non-essential categories.
Design the banner and preference center
clear accept all, decline all, and per-category choices.
Store evidence of consent
server-side storage of banner version, timestamp, status, and user/anonymous ID per internal policy.
Only load scripts after consent
use a loader service, don’t hardcode into HTML.
Allow users to change their mind
a footer link to reopen settings; when declined, stop loading new scripts.
When do you need a lawyer or a deeper review?
If your app uses remarketing, profiling, foreign SDKs, cross-border data transfers, or synchronizes consent with multiple systems like CRM/CDP/GA4/Meta, review the setup with counsel and your security team. The PDPL is new, and guiding decrees will clarify many technical details and specific penalties.
If you are building a banner, storing evidence of consent, or need to connect consent status with your backend/DSAR, consent.vn can help you design a practical flow for Angular instead of stopping at a popup.
- Not every script must be loaded dynamically, but non-essential scripts or those for analytics/marketing should only load after consent, per regulations.
- Use both if possible: localStorage for responsive UI, backend for evidence of consent and an audit trail.
- Not necessarily. Only guard functionality that depends on consent or third-party scripts.
- Yes, but you must ensure only non-essential cookies/scripts are disabled and that you don’t collect beyond the purposes disclosed under the regulations.
Source: the Personal Data Protection Law (Law 91/2025/QH15) and Decree 13/2023/ND-CP on thuvienphapluat.vn; enforcement agency A05 on bocongan.gov.vn
Get started — set up in 5 minutes.
Need help with PDPL compliance?