Event Logger
All product analytics flow through one service. Components and effects never call the Segment SDK directly.
EventLoggerService
src/app/core/pyb/services/event-logger.service.ts
@Injectable({ providedIn: 'root' })
export class EventLoggerService {
constructor(private readonly segment: SegmentService) {}
public identify(user: User) {
this.segment.identify(user.id, UserIdentificationModel.fromDto(user)).then();
}
public track(event: EventTypesInterface) {
console.log('Tracking: ', event); (1)
this.segment.track(event.eventMessage, event?.additionalProperties).then();
}
}
| 1 | Every tracked event is logged to the console, in all environments including production. Useful when verifying instrumentation; noisy otherwise. |
|
Both calls end in |
Event shape
export interface EventTypesInterface {
eventMessage: string; // the Segment event name
additionalProperties?: any; // optional properties object
}
eventMessage should always come from an enum in
src/app/core/pyb/enums/event-types.enum.ts, never a string literal.
Identification
identify() is called from AuthEffects.loadUser$, immediately after the user is
fetched and before userLoaded is dispatched:
switchMap(() => this.auth.getUserByToken()),
tap(user => {
this.eventLogger.identify(user);
return user;
}),
Traits sent to Segment:
export class UserIdentificationModel {
legalName: string;
firstName: string;
lastName: string;
email: string;
phone: string;
company: { id: string; name: string };
static fromDto(user: User): UserIdentificationModel {
const model = new UserIdentificationModel();
model.legalName = user.companyName;
model.firstName = user.firstName;
model.lastName = user.lastName;
model.email = user.email;
model.phone = user.phone;
model.company = { id: user.id, name: user.companyName };
return model;
}
}
The Segment user id is user.id — the supplier key.
|
|
|
No product-state traits (status, schema, permissions, product flags) are sent. Segment-side segmentation on those attributes is not possible with the current payload. |
Segment configuration
SegmentModule.forRoot({
apiKey: environment.segmentKey,
debug: false,
loadOnInitialization: environment.production, (1)
})
| 1 | Segment only auto-loads in production. Outside production the SDK is
configured but not loaded, so track() calls resolve without reaching
Segment. Verify instrumentation using the console log, not the Segment
debugger. |
An additional pre-bundled helper, src/eventLogger.bundle.min.js, ships outside
the Angular build.
Emitting an event
this.eventLoggerService.track({
eventMessage: AdvanceLineEventTypes.FUNDS_WITHDRAWN,
additionalProperties: { offerType, amount },
});
Without properties:
this.eventLoggerService.track({ eventMessage: AirwallexCardEventTypes.CARD_BLOCKED });
Typical placement:
In an operation service |
After the API call succeeds — |
In a DocuSign handler |
Around the confirmation and the business action. |
In a guard |
|
In an effect |
For store-driven events such as |
Specialised trackers
|
Emits |
|
Amazon Seller Central connection events. |
Both delegate to EventLoggerService; they exist to keep event-shaping logic out
of components.
Adding an event
-
Add the member to the appropriate enum in
event-types.enum.ts— or create a new enum if it is a new domain. -
Inject
EventLoggerService. -
Call
track()with the enum member and any properties. -
Add the event to Event Catalog.
|
Segment event names are effectively permanent — renaming one breaks every downstream dashboard and audience. Add a new member rather than editing an existing value. |