01
Install the packages
pnpm add @pact/web @pact/runtime02
Install the bootstrap
This is the enforcement boundary. Keep it server-rendered and before optional code.
typescript
<script
id="pact-bootstrap"
data-tenant="site_live_your_key"
data-src="/pact.js"
data-api="/v1">
((e,r,o)=>{let a=location.search,c=(a.match(/region=(CA|TX|EU)/)||[,"CA"])[1],n=r.currentScript.dataset,t="1"==n.gpc||o.globalPrivacyControl||a.includes("gpc=1"),i=!t&&"EU"!=c&&"0"!=n.allow,l=n.src||"/pact.js",p=()=>import(l);(e.pact={ready:0,purposes:{marketing:i},gpc:!!t,region:c,on:()=>()=>0,allow:p,deny:p,openPreferences:p}).ready="TX"==c?Promise.resolve():p()})(window,document,navigator);
</script>03
Wire Angular
html
<script
id="pact-bootstrap"
data-tenant="site_live_your_key"
data-src="/pact.js"
data-api="/v1">
((e,r,o)=>{let a=location.search,c=(a.match(/region=(CA|TX|EU)/)||[,"CA"])[1],n=r.currentScript.dataset,t="1"==n.gpc||o.globalPrivacyControl||a.includes("gpc=1"),i=!t&&"EU"!=c&&"0"!=n.allow,l=n.src||"/pact.js",p=()=>import(l);(e.pact={ready:0,purposes:{marketing:i},gpc:!!t,region:c,on:()=>()=>0,allow:p,deny:p,openPreferences:p}).ready="TX"==c?Promise.resolve():p()})(window,document,navigator);
</script>
<app-root></app-root>04
src/main.ts
ts
import { definePactElements } from '@pact/web'
definePactElements()
bootstrapApplication(AppComponent)05
src/app.component.ts
ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
@Component({
selector: 'app-root',
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<pact-gate purpose="analytics"><app-analytics /></pact-gate>
<pact-preferences-button>Privacy choices</pact-preferences-button>
`,
})
export class AppComponent {}