From a48db8763e414ae65e28d89ac04eca93a49a871e Mon Sep 17 00:00:00 2001 From: Manuel Borrajo <98417315+m-borrajo@users.noreply.github.com> Date: Wed, 18 Oct 2023 13:35:05 -0300 Subject: [PATCH 1/5] Add unit test --- projects/pixel/src/lib/pixel.service.spec.ts | 32 +++++++++- projects/pixel/src/lib/pixel.service.ts | 62 ++++++++++++-------- tsconfig.json | 11 +--- 3 files changed, 71 insertions(+), 34 deletions(-) diff --git a/projects/pixel/src/lib/pixel.service.spec.ts b/projects/pixel/src/lib/pixel.service.spec.ts index 2827af5..924653b 100644 --- a/projects/pixel/src/lib/pixel.service.spec.ts +++ b/projects/pixel/src/lib/pixel.service.spec.ts @@ -1,16 +1,46 @@ import { TestBed } from '@angular/core/testing'; import { PixelService } from './pixel.service'; +import { PLATFORM_ID } from '@angular/core'; +import { PixelEventName, PixelEventProperties } from './pixel.models'; + +declare const fbq: ( + type: 'track' | 'trackCustom', + eventName: PixelEventName | string, + properties?: PixelEventProperties +) => void; describe('PixelService', () => { let service: PixelService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + providers: [ + { provide: 'config', useValue: { enabled: true, pixelId: '123000' } }, + ], + }); service = TestBed.inject(PixelService); }); it('should be created', () => { expect(service).toBeTruthy(); }); + + it('should console a warning when the script was already loaded', () => { + service.initialize('12000'); + spyOn(console, 'warn'); + service.initialize('12000'); + expect(console.warn).toHaveBeenCalledWith( + 'Tried to initialize a Pixel instance while another is already active. Please call `remove()` before initializing a new instance.' + ); + }); + + it('should console a warning when the script wasnt loaded', () => { + service.remove(); + spyOn(console, 'warn'); + service.track('AddToCart'); + expect(console.warn).toHaveBeenCalledWith( + 'Tried to track an event without initializing a Pixel instance. Call `initialize()` first.' + ); + }); }); diff --git a/projects/pixel/src/lib/pixel.service.ts b/projects/pixel/src/lib/pixel.service.ts index a85b4d5..dcad723 100644 --- a/projects/pixel/src/lib/pixel.service.ts +++ b/projects/pixel/src/lib/pixel.service.ts @@ -1,18 +1,32 @@ -import { PixelEventName, PixelConfiguration, PixelEventProperties } from './pixel.models'; -import { Inject, Injectable, Optional, PLATFORM_ID, Renderer2, RendererFactory2 } from '@angular/core'; +import { + PixelEventName, + PixelConfiguration, + PixelEventProperties, +} from './pixel.models'; +import { + Inject, + Injectable, + Optional, + PLATFORM_ID, + Renderer2, + RendererFactory2, +} from '@angular/core'; import { NavigationEnd, Router } from '@angular/router'; import { DOCUMENT, isPlatformBrowser } from '@angular/common'; import { filter } from 'rxjs/operators'; -declare const fbq: any; +declare const fbq: ( + type: 'track' | 'trackCustom', + eventName: PixelEventName | string, + properties?: PixelEventProperties +) => void; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class PixelService { - private doc: Document; - private renderer: Renderer2 + private renderer: Renderer2; constructor( @Inject('config') private config: PixelConfiguration, @@ -21,7 +35,6 @@ export class PixelService { @Optional() private router: Router, private rendererFactory: RendererFactory2 ) { - // DOCUMENT cannot be injected directly as Document type, see https://github.com/angular/angular/issues/20351 // It is therefore injected as any and then cast to Document this.doc = injectedDocument as Document; @@ -29,15 +42,14 @@ export class PixelService { if (router) { // Log page views after router navigation ends - router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(event => { - - if (this.isLoaded()) { - this.track('PageView'); - } - - }); + router.events + .pipe(filter((event) => event instanceof NavigationEnd)) + .subscribe((event) => { + if (this.isLoaded()) { + this.track('PageView'); + } + }); } - } /** @@ -47,7 +59,9 @@ export class PixelService { */ initialize(pixelId = this.config.pixelId): void { if (this.isLoaded()) { - console.warn('Tried to initialize a Pixel instance while another is already active. Please call `remove()` before initializing a new instance.'); + console.warn( + 'Tried to initialize a Pixel instance while another is already active. Please call `remove()` before initializing a new instance.' + ); return; } this.config.enabled = true; @@ -67,16 +81,15 @@ export class PixelService { * @param eventName The name of the event that is being tracked * @param properties Optional properties of the event */ - track( - eventName: PixelEventName, - properties?: PixelEventProperties - ): void { + track(eventName: PixelEventName, properties?: PixelEventProperties): void { if (!isPlatformBrowser(this.platformId)) { return; } if (!this.isLoaded()) { - console.warn('Tried to track an event without initializing a Pixel instance. Call `initialize()` first.'); + console.warn( + 'Tried to track an event without initializing a Pixel instance. Call `initialize()` first.' + ); return; } @@ -85,7 +98,6 @@ export class PixelService { } else { fbq('track', eventName); } - } /** @@ -101,7 +113,9 @@ export class PixelService { } if (!this.isLoaded()) { - console.warn('Tried to track an event without initializing a Pixel instance. Call `initialize()` first.'); + console.warn( + 'Tried to track an event without initializing a Pixel instance. Call `initialize()` first.' + ); return; } @@ -133,7 +147,6 @@ export class PixelService { fbq('init', '${pixelId}'); fbq('track', 'PageView');`; - const scriptElement = this.renderer.createElement('script'); this.renderer.setAttribute(scriptElement, 'id', 'pixel-script'); this.renderer.setAttribute(scriptElement, 'type', 'text/javascript'); @@ -160,5 +173,4 @@ export class PixelService { } return false; } - } diff --git a/tsconfig.json b/tsconfig.json index 7bb287a..2266b23 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,18 +15,13 @@ "importHelpers": true, "target": "es2015", "module": "es2020", - "lib": [ - "es2018", - "dom" - ], + "lib": ["es2018", "dom"], "paths": { - "pixel": [ - "dist/pixel/pixel", - "dist/pixel" - ] + "pixel": ["dist/pixel/pixel", "dist/pixel"] } }, "angularCompilerOptions": { + "enableIvy": true, "strictInjectionParameters": true, "strictInputAccessModifiers": true, "strictTemplates": true From 6cc394b3aaaf572d9a4eed01aa8bbba4382c9a5e Mon Sep 17 00:00:00 2001 From: Manuel Borrajo <98417315+m-borrajo@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:27:31 -0300 Subject: [PATCH 2/5] Add unit test --- projects/pixel/src/lib/pixel.service.spec.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/projects/pixel/src/lib/pixel.service.spec.ts b/projects/pixel/src/lib/pixel.service.spec.ts index 924653b..d9693bf 100644 --- a/projects/pixel/src/lib/pixel.service.spec.ts +++ b/projects/pixel/src/lib/pixel.service.spec.ts @@ -4,11 +4,6 @@ import { PixelService } from './pixel.service'; import { PLATFORM_ID } from '@angular/core'; import { PixelEventName, PixelEventProperties } from './pixel.models'; -declare const fbq: ( - type: 'track' | 'trackCustom', - eventName: PixelEventName | string, - properties?: PixelEventProperties -) => void; describe('PixelService', () => { let service: PixelService; From 13f6bdd9072b485dd0f5861a0feb8b709ae4bc2b Mon Sep 17 00:00:00 2001 From: Manuel Borrajo <98417315+m-borrajo@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:43:16 -0300 Subject: [PATCH 3/5] Add setting: mobileBridge --- projects/pixel/README.md | 12 +++++++++++- projects/pixel/src/lib/pixel.models.ts | 2 ++ projects/pixel/src/lib/pixel.module.ts | 2 +- projects/pixel/src/lib/pixel.service.ts | 10 ++++++++-- tsconfig.json | 1 - 5 files changed, 22 insertions(+), 5 deletions(-) diff --git a/projects/pixel/README.md b/projects/pixel/README.md index 1cc89b9..5cd31d0 100644 --- a/projects/pixel/README.md +++ b/projects/pixel/README.md @@ -140,6 +140,16 @@ export class HomeComponent { } ``` +## Enabling mobileBridge to Hybrid Mobile App Events ***ngx-pixel*** +It sends the events to app container following this link: https://developers.facebook.com/docs/app-events/hybrid-app-events/. +When adding ***ngx-pixel*** to `app.module.ts`, add the parameter `appId: 'YOUR_PIXEL_APP_ID'`. +```TypeScript +imports: [ + BrowserModule, + PixelModule.forRoot({ enabled: true, pixelId: 'YOUR_PIXEL_ID', appId: 'YOUR_PIXEL_APP_ID'}) +], +``` + --- # Important notes @@ -149,7 +159,7 @@ export class HomeComponent { # What's next? - [X] Adding Angular Universal SSR support. -- [ ] Adding tests. +- [X] Adding tests. - [ ] Removing all Facebook scripts on removal, not just the initial script. --- diff --git a/projects/pixel/src/lib/pixel.models.ts b/projects/pixel/src/lib/pixel.models.ts index 7108c01..11d1ffe 100644 --- a/projects/pixel/src/lib/pixel.models.ts +++ b/projects/pixel/src/lib/pixel.models.ts @@ -3,6 +3,8 @@ export interface PixelConfiguration { enabled?: boolean; /** Your Facebook Pixel ID */ pixelId: string; + /** Your Facebook APP ID, only is required to mobileBridge */ + appId?: string; } export interface PixelEventProperties { diff --git a/projects/pixel/src/lib/pixel.module.ts b/projects/pixel/src/lib/pixel.module.ts index 7334b99..a57b671 100644 --- a/projects/pixel/src/lib/pixel.module.ts +++ b/projects/pixel/src/lib/pixel.module.ts @@ -34,7 +34,7 @@ export class PixelModule { return { ngModule: PixelModule, - providers: [PixelService, { provide: 'config', useValue: config }] + providers: [PixelService, { provide: 'config', useValue: config }], }; } diff --git a/projects/pixel/src/lib/pixel.service.ts b/projects/pixel/src/lib/pixel.service.ts index dcad723..4e68ab7 100644 --- a/projects/pixel/src/lib/pixel.service.ts +++ b/projects/pixel/src/lib/pixel.service.ts @@ -65,7 +65,7 @@ export class PixelService { return; } this.config.enabled = true; - this.addPixelScript(pixelId); + this.addPixelScript(pixelId, this.config.appId); } /** Remove the Pixel tracking script */ @@ -129,12 +129,17 @@ export class PixelService { /** * Adds the Facebook Pixel tracking script to the application * @param pixelId The Facebook Pixel ID to use + * @param appId The Facebook Pixel APP ID to use */ - private addPixelScript(pixelId: string): void { + private addPixelScript(pixelId: string, appId?: string): void { if (!isPlatformBrowser(this.platformId)) { return; } + const scriptMobileBridge = appId + ? `fbq('set', 'mobileBridge', '${pixelId}', '${appId}')` + : ''; + const pixelCode = ` var pixelCode = function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? @@ -145,6 +150,7 @@ export class PixelService { s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', '${pixelId}'); + ${scriptMobileBridge} fbq('track', 'PageView');`; const scriptElement = this.renderer.createElement('script'); diff --git a/tsconfig.json b/tsconfig.json index 2266b23..1acb17c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,6 @@ } }, "angularCompilerOptions": { - "enableIvy": true, "strictInjectionParameters": true, "strictInputAccessModifiers": true, "strictTemplates": true From 38de1ee7ed4ed8fbe5fd8bab2a1878d6da1710cd Mon Sep 17 00:00:00 2001 From: Manuel Borrajo <98417315+m-borrajo@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:43:52 -0300 Subject: [PATCH 4/5] Update README.md --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5747cbe..b354ca7 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,15 @@ export class HomeComponent { } ``` - +## Enabling mobileBridge to Hybrid Mobile App Events ***ngx-pixel*** +It sends the events to app container following this link: https://developers.facebook.com/docs/app-events/hybrid-app-events/. +When adding ***ngx-pixel*** to `app.module.ts`, add the parameter `appId: 'YOUR_PIXEL_APP_ID'`. +```TypeScript +imports: [ + BrowserModule, + PixelModule.forRoot({ enabled: true, pixelId: 'YOUR_PIXEL_ID', appId: 'YOUR_PIXEL_APP_ID'}) +], +``` --- # Important notes From 16dca2c07e8a3d80251a80583c2d926de023e223 Mon Sep 17 00:00:00 2001 From: Manuel Borrajo <98417315+m-borrajo@users.noreply.github.com> Date: Wed, 18 Oct 2023 21:44:45 -0300 Subject: [PATCH 5/5] Checked tests --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b354ca7..c51ff3b 100644 --- a/README.md +++ b/README.md @@ -158,7 +158,7 @@ imports: [ # What's next? - [X] Adding Angular Universal SSR support. -- [ ] Adding tests. +- [X] Adding tests. - [ ] Removing all Facebook scripts on removal, not just the initial script. ---