Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Cloudflare Web Analytics #15

Merged
merged 3 commits into from
May 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"format": "prettier --write src/**/*.{ts,html,scss}",
"test": "ng test",
"test:ci": "ng test --configuration production",
"lint": "ng lint && stylelint src/**/*.scss --fix",
"lint": "ng lint && stylelint src/**/*.scss --fix && prettier --check src/**/*.{ts,html,scss}",
"release": "release-it",
"e2e": "ng e2e",
"cy:open": "cypress open",
Expand Down
34 changes: 34 additions & 0 deletions src/app/analytics.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Injectable } from '@angular/core';

import { Observable } from 'rxjs';

@Injectable({
providedIn: 'root',
})
export class AnalyticsService {
/**
* Injects a script to track web analytics using Cloudflare's beacon.min.js.
*
* @return {Observable<Event>} An observable that emits an event when the script is successfully injected,
* or an error event if the injection fails.
*/
injectScript(): Observable<Event> {
return new Observable((observer) => {
const script = document.createElement('script');
script.defer = true;
script.type = 'text/javascript';
script.src = 'https://static.cloudflareinsights.com/beacon.min.js';
script.setAttribute('data-cf-beacon', '{"token": "f35c166c64154ae5822d35b80f4ed71e"}');

script.onload = () => {
observer.next(new Event('Cloudflare Web Analytics injected'));
observer.complete();
};
script.onerror = () => {
observer.error('Cloudflare Web Analytics injection failed');
};

document.head.appendChild(script);
});
}
}
16 changes: 14 additions & 2 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { CommonModule } from '@angular/common';
import { Component, inject } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { DomSanitizer } from '@angular/platform-browser';
import { RouterModule, RouterOutlet } from '@angular/router';

import { environment as env } from '../environments/environment';
import { AnalyticsService } from './analytics.service';
import { LoginComponent } from './login/login.component';
import { AuthService } from './shared/services/auth/auth.service';

Expand All @@ -23,8 +25,9 @@ import { AuthService } from './shared/services/auth/auth.service';
],
templateUrl: './app.component.html',
})
export class AppComponent {
export class AppComponent implements OnInit {
auth = inject(AuthService);
analytics = inject(AnalyticsService);

constructor(iconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
iconRegistry.addSvgIcon(
Expand All @@ -36,4 +39,13 @@ export class AppComponent {
sanitizer.bypassSecurityTrustResourceUrl('assets/images/charts.svg'),
);
}

ngOnInit() {
if (env.production) {
this.analytics.injectScript().subscribe({
next: console.log,
error: console.error,
});
}
}
}
18 changes: 14 additions & 4 deletions src/app/privacy/privacy.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ <h1>Privacy Policy</h1>
data when you use our site, app, and services (refer to as the "App" from here on), and the
choices you have associated with that data.
</p>
<p><em>This application is not affiliated with YNAB</em>.</p>
<h2>YNAB Data and OAuth</h2>
<p>
The App follows
<a class="text-blue-800 underline" href="https://api.ynab.com/#terms"
>Terms of Service for the YNAB API</a
The App follows YNAB's
<a class="text-blue-800 underline" href="https://api.ynab.com/#terms">API Terms of Service</a>
and
<a class="text-blue-800 underline" href="https://api.ynab.com/#oauth-requirements"
>OAuth application requirements</a
>:
</p>
<ul class="list-disc">
Expand All @@ -23,7 +26,14 @@ <h2>YNAB Data and OAuth</h2>
<li>The application will never ask for any financial account credentials.</li>
</ul>
<h2 class="!mt-3">We collect</h2>
<p>We do not collect any information from your YNAB account.</p>
<p>
We do not collect any information from your YNAB account. We use
<a
class="text-blue-800 underline"
href="https://developers.cloudflare.com/analytics/web-analytics/"
>Cloudflare Web Analytics</a
>, which is a privacy-first analytics tool, to monitor activity on the site.
</p>
<h2>Data Removal</h2>
<p>
When you logout of the App, all your YNAB data and the App's own preferences are cleared from
Expand Down
Loading