Angular Integration (@angular/core v14 to 18+)
Complete guide for integrating ParityEdge localized purchasing power parity pricing into Angular applications using Standalone Components, Angular Signals (toSignal), RxJS HttpClient Services, and Shadow DOM Web Components.
Enable CUSTOM_ELEMENTS_SCHEMA & Load Global CDN
Because the ParityEdge banner is rendered in an isolated Shadow DOM custom element, configure your Angular component or module with CUSTOM_ELEMENTS_SCHEMA:
Load CDN Script in src/index.html (or angular.json)
<!-- src/index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Angular App</title>
<base href="/">
<!-- ParityEdge Sub-10ms Edge CDN Script -->
<script
src="https://api.parityedge.app/v1/parity.global.js"
async
></script>
</head>
<body>
<app-root></app-root>
</body>
</html>Configure Standalone Angular Component (pricing.component.ts)
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { CommonModule } from '@angular/common';
@Component({
selector: 'app-pricing',
standalone: true,
imports: [CommonModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA], // Enables <parity-element> web component
template: `
<div class="pricing-container">
<!-- Isolated Shadow DOM Web Component Banner (Near-Zero CLS) -->
<parity-element
[attr.project-id]="projectId"
theme="dark"
position="bottom-pill">
</parity-element>
<h1>Simple, Predictable Pricing</h1>
<!-- Pricing cards here -->
</div>
`,
styles: [`
.pricing-container {
min-height: 100vh;
background-color: #0a0e17;
color: #ffffff;
padding: 3rem 1rem;
}
`]
})
export class PricingComponent {
projectId = 'prj_live_YOUR_PROJECT_ID';
}Type-Safe ParityEdgeService with Angular Signals
For full UI control, inject an Angular HTTP Service that communicates with the ParityEdge Edge API, exposing reactive state via Angular Signals (toSignal):
src/app/services/parity-edge.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, shareReplay, catchError, of } from 'rxjs';
export interface ParityResolution {
eligible: boolean;
countryCode: string;
countryName: string;
discountPercentage: number;
couponCode: string;
currency: string;
tier: number;
}
@Injectable({
providedIn: 'root'
})
export class ParityEdgeService {
private http = inject(HttpClient);
private edgeApiUrl = 'https://api.parityedge.app/v1/lookup';
resolveParity(projectId: string): Observable<ParityResolution | null> {
return this.http.get<ParityResolution>(`${this.edgeApiUrl}?projectId=${projectId}`).pipe(
shareReplay(1),
catchError((err) => {
console.warn('[ParityEdge] Resolution fallback to default USD:', err);
return of(null);
})
);
}
}src/app/components/pricing-table.component.ts (Angular 16+)
import { Component, inject, computed } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { CommonModule } from '@angular/common';
import { ParityEdgeService } from '../services/parity-edge.service';
@Component({
selector: 'app-pricing-table',
standalone: true,
imports: [CommonModule],
template: `
<div class="p-6 rounded-2xl border border-slate-800 bg-slate-900 text-white space-y-4">
<h3>Pro Tier</h3>
<!-- Dynamic Price Calculation with Signal -->
<div class="text-3xl font-extrabold">
${{ discountedPrice() }} <span class="text-xs text-slate-400">/ month</span>
</div>
<!-- Discount Notification Pill -->
@if (parity()?.eligible && (parity()?.discountPercentage ?? 0) > 0) {
<div class="p-3 bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 rounded-xl text-xs font-medium">
<span>{{ parity()?.discountPercentage }}% Parity Discount applied for {{ parity()?.countryName }}!</span>
<code class="ml-2 bg-emerald-950 px-2 py-0.5 rounded">Code: {{ parity()?.couponCode }}</code>
</div>
}
<button
(click)="checkout()"
class="w-full py-2.5 px-4 rounded-xl bg-emerald-500 hover:bg-emerald-600 text-white font-semibold text-xs transition-all">
Subscribe Now
</button>
</div>
`
})
export class PricingTableComponent {
private parityService = inject(ParityEdgeService);
private baseUsdPrice = 49;
// Reactive Signal directly from Edge API
readonly parity = toSignal(
this.parityService.resolveParity('prj_live_YOUR_PROJECT_ID')
);
// Computed signal for discounted price
readonly discountedPrice = computed(() => {
const data = this.parity();
if (!data || !data.eligible || data.discountPercentage <= 0) return this.baseUsdPrice.toFixed(2);
return (this.baseUsdPrice * (1 - data.discountPercentage / 100)).toFixed(2);
});
checkout() {
const coupon = this.parity()?.couponCode;
window.location.href = coupon
? `https://buy.stripe.com/test_123?prefilled_promo_code=${coupon}`
: 'https://buy.stripe.com/test_123';
}
}Angular Production Architecture Highlights
Reactive Signal Caching
shareReplay(1) prevents duplicate HTTP requests on route changes, maintaining instant local state across views.
Anti-VPN Edge Validation
ParityEdge validates ASN threats at the Anycast edge layer, guaranteeing that datacenter proxies do not receive discounted rates.