diff --git a/src/app/providers/providers.component.ts b/src/app/providers/providers.component.ts
index 59d5dfa..20b13fb 100644
--- a/src/app/providers/providers.component.ts
+++ b/src/app/providers/providers.component.ts
@@ -94,6 +94,11 @@ export class ProvidersComponent {
display: 'Matomo',
type: 'Analytics',
},
+ {
+ name: 'posthog',
+ display: 'Posthog',
+ type: 'Analytics',
+ },
{
name: 'segment',
display: 'Segment',
diff --git a/src/assets/svg/posthog.svg b/src/assets/svg/posthog.svg
new file mode 100644
index 0000000..0a64d1d
--- /dev/null
+++ b/src/assets/svg/posthog.svg
@@ -0,0 +1 @@
+
diff --git a/src/lib/providers/posthog/README.md b/src/lib/providers/posthog/README.md
new file mode 100644
index 0000000..e01931c
--- /dev/null
+++ b/src/lib/providers/posthog/README.md
@@ -0,0 +1,11 @@
+
+
+# Posthog
+
+**homepage**: [posthog.com](https://posthog.com/)
+**docs**: [posthog.com/docs/product-analytics](https://posthog.com/docs/product-analytics)
+**import**: `import { Angulartics2Posthog } from 'angulartics2';`
diff --git a/src/lib/providers/posthog/posthog.spec.ts b/src/lib/providers/posthog/posthog.spec.ts
new file mode 100644
index 0000000..f0f1dc3
--- /dev/null
+++ b/src/lib/providers/posthog/posthog.spec.ts
@@ -0,0 +1,169 @@
+import { fakeAsync, inject, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { advance, createRoot, RootCmp, TestModule } from '../../test.mocks';
+
+import { Angulartics2 } from '../../angulartics2-core';
+import { Angulartics2Posthog } from './posthog';
+
+jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
+declare var window: any;
+
+describe('Angulartics2Posthog', () => {
+ let fixture: ComponentFixture;
+ let posthog: any;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ imports: [TestModule],
+ providers: [Angulartics2Posthog],
+ });
+
+ window.posthog = posthog = {
+ capture: jasmine.createSpy('capture'),
+ identify: jasmine.createSpy('identify'),
+ alias: jasmine.createSpy('alias'),
+ };
+
+ const provider: Angulartics2Posthog = TestBed.inject(Angulartics2Posthog);
+ provider.startTracking();
+ });
+
+ it('should track pages', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.pageTrack.next({ path: '/abc' });
+ advance(fixture);
+ expect(posthog.capture).toHaveBeenCalledWith('Page Viewed', {
+ page: '/abc',
+ });
+ },
+ ),
+ ));
+
+ it('should track events', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.eventTrack.next({
+ action: 'do',
+ properties: { category: 'cat' },
+ });
+ advance(fixture);
+ expect(posthog.capture).toHaveBeenCalledWith('do', { category: 'cat' });
+ },
+ ),
+ ));
+
+ it('should set username', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.setUsername.next('testUser');
+ advance(fixture);
+ expect(posthog.identify).toHaveBeenCalledWith('testUser');
+ },
+ ),
+ ));
+
+ it('should set user properties', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.setUserProperties.next({
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ });
+ advance(fixture);
+ expect(posthog.identify).toHaveBeenCalledWith('1', {
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ });
+ },
+ ),
+ ));
+
+ it('should set user properties once', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.setUserPropertiesOnce.next({
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ });
+ advance(fixture);
+ expect(posthog.capture).toHaveBeenCalledWith('Set User Properties Once', {
+ $set_once: {
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ }
+ });
+ },
+ ),
+ ));
+
+ it('should set super properties', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.setSuperProperties.next({
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ });
+ advance(fixture);
+ expect(posthog.capture).toHaveBeenCalledWith('Set Super Properties', {
+ $set: {
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ }
+ });
+ },
+ ),
+ ));
+
+ it('should set super properties once', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.setSuperPropertiesOnce.next({
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ });
+ advance(fixture);
+ expect(posthog.capture).toHaveBeenCalledWith('Set Super Properties Once', {
+ $set_once: {
+ distinct_id: '1',
+ firstName: 'John',
+ lastName: 'Doe',
+ }
+ });
+ },
+ ),
+ ));
+
+ it('should set alias', fakeAsync(
+ inject(
+ [Angulartics2, Angulartics2Posthog],
+ (angulartics2: Angulartics2, angulartics2Posthog: Angulartics2Posthog) => {
+ fixture = createRoot(RootCmp);
+ angulartics2.setAlias.next('testAlias');
+ advance(fixture);
+ expect(posthog.alias).toHaveBeenCalledWith('testAlias');
+ },
+ ),
+ ));
+});
diff --git a/src/lib/providers/posthog/posthog.ts b/src/lib/providers/posthog/posthog.ts
new file mode 100644
index 0000000..2e68df6
--- /dev/null
+++ b/src/lib/providers/posthog/posthog.ts
@@ -0,0 +1,119 @@
+import { inject, Injectable } from '@angular/core';
+import { Angulartics2 } from '../../angulartics2-core';
+
+declare let posthog: any;
+
+@Injectable({ providedIn: 'root' })
+export class Angulartics2Posthog {
+ private readonly angulartics2 = inject(Angulartics2);
+
+ constructor() {
+ this.angulartics2.setUsername.subscribe(x => this.setUsername(x));
+ this.angulartics2.setUserProperties.subscribe(x => this.setUserProperties(x));
+ this.angulartics2.setUserPropertiesOnce.subscribe(x => this.setUserPropertiesOnce(x));
+ this.angulartics2.setSuperProperties.subscribe(x => this.setSuperProperties(x));
+ this.angulartics2.setSuperPropertiesOnce.subscribe(x => this.setSuperPropertiesOnce(x));
+ this.angulartics2.setAlias.subscribe(x => this.setAlias(x));
+ }
+
+ startTracking(): void {
+ this.startPageTracking();
+ this.startEventTracking();
+ }
+
+ startPageTracking(): void {
+ this.angulartics2.pageTrack.pipe(this.angulartics2.filterDeveloperMode()).subscribe(x => {
+ this.pageTrack(x.path);
+ });
+ }
+
+ startEventTracking(): void {
+ this.angulartics2.eventTrack.pipe(this.angulartics2.filterDeveloperMode()).subscribe(x => {
+ this.eventTrack(x.action, x.properties);
+ });
+ }
+
+ pageTrack(path: string | undefined): void {
+ try {
+ posthog.capture('Page Viewed', { page: path });
+ } catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ eventTrack(action: string, properties?: any): void {
+ try {
+ posthog.capture(action, properties);
+ } catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ setUsername(userId: string | { userId: string | number }): void {
+ try {
+ posthog.identify(userId);
+ } catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ setUserProperties(properties: any | undefined): void {
+ try {
+ posthog.identify(properties["distinct_id"], properties);
+ } catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ setUserPropertiesOnce(properties: any | undefined): void {
+ try {
+ posthog.capture('Set User Properties Once', {
+ $set_once: properties
+ });
+ }
+ catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ setSuperProperties(properties: any | undefined): void {
+ try {
+ posthog.capture('Set Super Properties', { $set: properties });
+ } catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ setSuperPropertiesOnce(properties: any | undefined): void {
+ try {
+ posthog.capture('Set Super Properties Once', { $set_once: properties });
+ } catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+
+ setAlias(alias: string): void {
+ try {
+ posthog.alias(alias);
+ }
+ catch (e) {
+ if (!(e instanceof ReferenceError)) {
+ throw e;
+ }
+ }
+ }
+}
diff --git a/src/lib/public_api.ts b/src/lib/public_api.ts
index 12c9321..4a9711f 100644
--- a/src/lib/public_api.ts
+++ b/src/lib/public_api.ts
@@ -20,6 +20,7 @@ export * from './providers/hubspot/hubspot';
export * from './providers/kissmetrics/kissmetrics';
export * from './providers/launch/launch';
export * from './providers/mixpanel/mixpanel';
+export * from './providers/posthog/posthog';
export * from './providers/pyze/pyze';
export * from './providers/matomo/matomo';
export * from './providers/segment/segment';