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 .then() with no handler. Failures in the Segment SDK resolve silently and never surface — analytics never break a user flow, but a broken Segment key produces no visible symptom either.

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.

UserIdentificationModel reads the deprecated flat fields on User (companyName, firstName, lastName, phone). If those are ever removed in favour of _personalInformation / _businessInformation, this model must be migrated at the same time or every identify call will send undefined traits.

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 — AirwallexCardBlockService tracks inside tap().

In a DocuSign handler

Around the confirmation and the business action.

In a guard

HelpCenterRedirectGuard tracks before redirecting.

In an effect

For store-driven events such as trackBlogNavigate.

Specialised trackers

MarketplaceEventsService

Emits MarketplaceEventType events for connection lifecycle changes.

AmazonEventTrackerService

Amazon Seller Central connection events.

Both delegate to EventLoggerService; they exist to keep event-shaping logic out of components.

Adding an event

  1. Add the member to the appropriate enum in event-types.enum.ts — or create a new enum if it is a new domain.

  2. Inject EventLoggerService.

  3. Call track() with the enum member and any properties.

  4. 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.