Skip to content

Commit

Permalink
feat: Add incendium provider (#458)
Browse files Browse the repository at this point in the history
  • Loading branch information
mewis committed Nov 2, 2022
1 parent 56cd9de commit 809b127
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 3 deletions.
9 changes: 6 additions & 3 deletions src/app/providers/providers.component.ts
Expand Up @@ -64,6 +64,11 @@ export class ProvidersComponent {
display: 'HubSpot',
type: 'Analytics',
},
{
name: 'incendium',
display: 'Incendium',
type: 'Analytics',
},
{
name: 'intercom',
display: 'Intercom',
Expand Down Expand Up @@ -114,9 +119,7 @@ export class ProvidersComponent {
for (const provider of this.providers) {
iconRegistry.addSvgIcon(
provider.name,
sanitizer.bypassSecurityTrustResourceUrl(
`/assets/svg/${provider.name}.svg`,
),
sanitizer.bypassSecurityTrustResourceUrl(`/assets/svg/${provider.name}.svg`),
);
}
}
Expand Down
30 changes: 30 additions & 0 deletions src/assets/svg/incendium.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
100 changes: 100 additions & 0 deletions src/lib/providers/incendium/README.md
@@ -0,0 +1,100 @@
<img
src="../../../assets/svg/incendium.svg"
alt="Incendium analytics logo"
height="100px"
width="200px" />

**homepage**: [incendium.ai](https://www.incendium.ai/)
**import**: `import { Angulartics2Incendium } from 'angulartics2';`

## Setup

1. Add tracking code provided by Incendium inside the header tag.

2. [Setup Angulartics](https://github.com/angulartics/angulartics2/tree/master#installation) using `Angulartics2Incendium`

```typescript
constructor(Angulartics2Incendium: Angulartics2Incendium) {
Angulartics2Incendium.startTracking();
}
```

3. Track Conversions, You can track conversions using Angulartics2 event tracking.
this can be done by adding the following to you html

```html
<button
angulartics2On="click"
angularticsAction="{{ eIncendiumEventNames.ADD_CONVERION }}"
[angularticsProperties]="{ key: 'my_trigger_as_assigned_in_incendium' }"
>
Btn click
</button>
```

Note that eIncendiumEventNames is a reference to IncendiumEventNames expoted from Angulartics2Incendium

Or you can fire the conversion in code for example

```typescript
this.angulartics2.eventTrack.next({
action: IncendiumEventNames.ADD_CONVERION,
properties: {
key: 'my_trigger_as_assigned_in_incendium',
},
});
```

4. Incendium allows for offline tracking, to do this you must record the conversion key provided when firing a conversion.
A example of this would be a contact form which you later convert on the phone, incendium allows you to assign revenue next to this original conversion using this key

to do this fire a conversion off as above.
you can then subscribe to incendiumResponse. once the conversion has been tracked and response is returned you can use this response how ever you like.

**_Dont forget to unsubscribe_**

An Example workflow of this would be

```typescript
export class Example implements OnInit {
private incSubscription;

constructor(
private angulartics2: Angulartics2,
private angulartics2Incendium: Angulartics2Incendium,
) {}

ngOnInit(): void {
this.incSubscription = this.angulartics2Incendium.incendiumResponse.subscribe({
next: v => {
if (v.type === IncendiumEventNames.ADD_CONVERION) {
this.submit(v.value);
}
},
error: e => {
console.error(e);
// submit without key or handle how you like
this.submit();
},
});
}

ngOnDestroy(): void {
// Dont forget to unsubscribe
this.incSubscription.unsubscribe();
}

onSubmit() {
this.angulartics2.eventTrack.next({
action: IncendiumEventNames.ADD_CONVERION,
properties: {
key: 'my_trigger_as_assigned_in_incendium',
},
});
}

submit(incendiumKey?: string) {
alert(`form submitted with ${incendiumKey ? `key ${incendiumKey}` : `no key`}`);
}
}
```
74 changes: 74 additions & 0 deletions src/lib/providers/incendium/incendium.spec.ts
@@ -0,0 +1,74 @@
import { fakeAsync, inject, ComponentFixture, TestBed } from '@angular/core/testing';

import { Angulartics2 } from '../../angulartics2-core';
import { advance, createRoot, RootCmp, TestModule } from '../../test.mocks';
import { Angulartics2Incendium, IncendiumEventNames } from './incendium';

jasmine.DEFAULT_TIMEOUT_INTERVAL = 5000;
declare var window: any;

describe('Angulartics2Incendium', () => {
let inc: any;
let fixture: ComponentFixture<any>;
let service: Angulartics2Incendium;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [TestModule],
providers: [Angulartics2Incendium],
});
window.inc = inc = jasmine.createSpy('inc').and.returnValue('test');

service = TestBed.inject(Angulartics2Incendium);
service.startTracking();
});

it('should track pages', fakeAsync(
inject(
[Angulartics2, Angulartics2Incendium],
(angulartics2: Angulartics2, Angulartics2Incendium: Angulartics2Incendium) => {
fixture = createRoot(RootCmp);
angulartics2.pageTrack.next({ path: '/abc' });
advance(fixture);
expect(inc).toHaveBeenCalledWith('run', false, true);
},
),
));

it('should track conversions', fakeAsync(
inject(
[Angulartics2, Angulartics2Incendium],
(angulartics2: Angulartics2, Angulartics2Incendium: Angulartics2Incendium) => {
fixture = createRoot(RootCmp);
angulartics2.eventTrack.next({
action: IncendiumEventNames.ADD_CONVERION,
properties: { key: 'test' },
});
advance(fixture);
expect(inc).toHaveBeenCalledTimes(2);
expect(inc).toHaveBeenCalledWith(IncendiumEventNames.ADD_CONVERION, 'test');
expect(inc).toHaveBeenCalledWith('go');
},
),
));

it('should track conversion and emit conversion key', fakeAsync(
inject(
[Angulartics2, Angulartics2Incendium],
(angulartics2: Angulartics2, Angulartics2Incendium: Angulartics2Incendium) => {
service.incendiumResponse.subscribe(message => {
expect(message).toEqual({
type: IncendiumEventNames.ADD_CONVERION,
value: 'test',
});
});
fixture = createRoot(RootCmp);
angulartics2.eventTrack.next({
action: IncendiumEventNames.ADD_CONVERION,
properties: { key: 'test' },
});
advance(fixture);
},
),
));
});
86 changes: 86 additions & 0 deletions src/lib/providers/incendium/incendium.ts
@@ -0,0 +1,86 @@
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
import { Angulartics2 } from '../../angulartics2-core';

enum EventNames {
RUN = 'run',
GO = 'go',
}

export enum IncendiumEventNames {
ADD_CONVERION = 'add_conversion',
}

interface IIncendiumResponse {
value: string;
type: IncendiumEventNames;
}

type TIncendiumParams =
| {
key: string;
}
| boolean;

declare var inc: (e: EventNames | IncendiumEventNames, v?: TIncendiumParams, g?: boolean) => string;
declare global {
interface Window {
INCENDIUM: any;
}
}

@Injectable({ providedIn: 'root' })
export class Angulartics2Incendium {
incendiumResponse = new Subject<Partial<IIncendiumResponse>>();

constructor(private angulartics2: Angulartics2) {
if (typeof inc === 'undefined') {
console.warn('Angulartics 2 Incendium Plugin: incendium global not found');
}
}

startTracking(): void {
this.angulartics2.pageTrack
.pipe(this.angulartics2.filterDeveloperMode())
.subscribe(x => this.pageTrack(x.path));

this.angulartics2.eventTrack
.pipe(this.angulartics2.filterDeveloperMode())
.subscribe(({ action, properties }) => this.trackAction(action, properties));
}

/**
* Track Page in Incendium
*
* @param path location
*/
pageTrack(path: string) {
inc(EventNames.RUN, false, true);
}

/**
* Track Action
*
* @param action Action name
* @param properties params
*/
async trackAction(action: string, properties: any) {
try {
switch (action as IncendiumEventNames) {
case IncendiumEventNames.ADD_CONVERION:
inc(IncendiumEventNames.ADD_CONVERION, properties.key);
break;

default:
break;
}
const res = await inc(EventNames.GO);
this.incendiumResponse.next({
value: res,
type: IncendiumEventNames.ADD_CONVERION,
});
} catch (error) {
this.incendiumResponse.error(error);
}
}
}

0 comments on commit 809b127

Please sign in to comment.