1. Introduction

Micronaut Segment library allows you to integrate Segment into your Micronaut or Grails applications.

Segment lets you send your analytics data to any service you want, without having to integrate with each one individually.

The library provides the following beans:

2. Installation

Micronaut Segment is available in the Maven Central repository.

Gradle
api 'com.agorapulse:micronaut-segment:2.0.0'
Maven
<dependency>
    <groupId>com.agorapulse</groupId>
    <artifactId>micronaut-segment</artifactId>
    <version>2.0.0</version>
</dependency>

3. Configuration

You need to provide segment.api-key configuration property to send information to Segment.

segment:
    api-key: some-key                                                                   (1)
    options:                                                                            (2)
      language: fr
1 Segment API key is required if you want to send records to Segment but can be ignored in the development environment
2 The legacy default options id, language, user-agent or intercom, use Message Transformation instead

You can rely on SegmentService bean being always present but if the API key is missing then no-op implementation is provided.

4. Usage

4.1. Segment Service

You can inject SegmentService into your beans in order to call Segment APIs. The bean is always present but no-op implementation is injected when the Segment API key is missing in the configuration.

Contrary to the native Analytics builder methods, all the methods in the SegmentService accepts maps with null values or null values in general. null arguments are ignored and maps containing null values are cleaned up.

Java
@Singleton
public class MyService {

    private final SegmentService segmentService;

    public MyService(SegmentService segmentService) {
        this.segmentService = segmentService;
    }

}
Groovy
@Singleton
class MyService {

    private final SegmentService segmentService

    MyService(SegmentService segmentService) {
        this.segmentService = segmentService
    }

}

4.1.1. Creating Aliases

You can alias existing user to another ID.

See the documentation for the further information.

Java
service.alias(PREVIOUS_ID, USER_ID);
Groovy
service.alias(PREVIOUS_ID, USER_ID)

4.1.2. Group Association

You can associate a user with a group, including advanced properties.

See the documentation for the further information.

Java
service.group(USER_ID, GROUP_ID, b -> b
    .traits("category", CATEGORY)
    .traits("section", SECTION)
    .traits("nullable", null)
    .timestamp(now)
    .anonymousId(ANONYMOUS_ID)
    .messageId(MESSAGE_ID)
    .integrationOptions("Google Analytics", "clientId", GOOGLE_ANALYTICS_ID)
    .enableIntegration("Something Enabled", true)
    .enableIntegration("Something Disabled", false)
    .context("ip", IP_ADDRESS)
    .context("language", LANGUAGE)
    .context("userAgent", USER_AGENT)
    .context("Intercom", INTERCOM)
    .context("nullable", null)
);
Groovy
service.group(USER_ID, GROUP_ID) {
    traits(
        category: CATEGORY,
        section : SECTION,
        nullable: null
    )

    timestamp INSTANT_NOW

    anonymousId ANONYMOUS_ID

    integrationOptions 'Google Analytics', [clientId: GOOGLE_ANALYTICS_ID]

    enableIntegration 'Something Enabled', true
    enableIntegration 'Something Disabled', false

    context(
        ip: IP_ADDRESS,
        language: LANGUAGE,
        userAgent: USER_AGENT,
        Intercom: INTERCOM,
        nullable: null
    )
}

4.1.3. Identification

You can identify users with their traits.

See the documentation for the further information.

Java
service.identify(USER_ID, b -> b
    .traits("category", CATEGORY)
    .traits("nullable", null)
    .timestamp(now)
    .anonymousId(ANONYMOUS_ID)
    .messageId(MESSAGE_ID)
    .integrationOptions("Google Analytics", "clientId", GOOGLE_ANALYTICS_ID)
    .enableIntegration("Something Enabled", true)
    .enableIntegration("Something Disabled", false)
    .context("ip", IP_ADDRESS)
    .context("language", LANGUAGE)
    .context("userAgent", USER_AGENT)
    .context("Intercom", INTERCOM)
    .context("nullable", null)
);
Groovy
service.identify(USER_ID) {
    traits(
        category: CATEGORY,
        nullable: null
    )

    timestamp INSTANT_NOW

    anonymousId ANONYMOUS_ID

    integrationOptions 'Google Analytics', [clientId: GOOGLE_ANALYTICS_ID]

    enableIntegration 'Something Enabled', true
    enableIntegration 'Something Disabled', false

    context(
        ip: IP_ADDRESS,
        language: LANGUAGE,
        userAgent: USER_AGENT,
        Intercom: INTERCOM,
        nullable: null
    )
}

4.1.4. Page Views

You can record page view by the user with additional properties.

See the documentation for the further information.

Java
service.page(USER_ID, NAME, b -> b
    .properties("category", CATEGORY)
    .properties("section", SECTION)
    .properties("nullable", null)
    .timestamp(now)
    .anonymousId(ANONYMOUS_ID)
    .messageId(MESSAGE_ID)
    .integrationOptions("Google Analytics", "clientId", GOOGLE_ANALYTICS_ID)
    .enableIntegration("Something Enabled", true)
    .enableIntegration("Something Disabled", false)
    .context("ip", IP_ADDRESS)
    .context("language", LANGUAGE)
    .context("userAgent", USER_AGENT)
    .context("Intercom", INTERCOM)
    .context("nullable", null)
);
Groovy
service.page(USER_ID, NAME) {
    properties(
        category: CATEGORY,
        section: SECTION,
        nullable: null
    )

    timestamp INSTANT_NOW

    anonymousId ANONYMOUS_ID

    integrationOptions 'Google Analytics', [clientId: GOOGLE_ANALYTICS_ID]

    enableIntegration 'Something Enabled', true
    enableIntegration 'Something Disabled', false

    context(
        ip: IP_ADDRESS,
        language: LANGUAGE,
        userAgent: USER_AGENT,
        Intercom: INTERCOM,
        nullable: null
    )
}

4.1.5. Screen Views

You can record screen view by the user with additional properties.

See the documentation for the further information.

Java
service.screen(USER_ID, NAME, b -> b
    .properties("category", CATEGORY)
    .properties("section", SECTION)
    .properties("nullable", null)
    .timestamp(now)
    .anonymousId(ANONYMOUS_ID)
    .messageId(MESSAGE_ID)
    .integrationOptions("Google Analytics", "clientId", GOOGLE_ANALYTICS_ID)
    .enableIntegration("Something Enabled", true)
    .enableIntegration("Something Disabled", false)
    .context("ip", IP_ADDRESS)
    .context("language", LANGUAGE)
    .context("userAgent", USER_AGENT)
    .context("Intercom", INTERCOM)
    .context("nullable", null)
);
Groovy
service.screen(USER_ID, NAME) {
    properties(
        category: CATEGORY,
        section: SECTION,
        nullable: null
    )

    timestamp INSTANT_NOW

    anonymousId ANONYMOUS_ID

    integrationOptions 'Google Analytics', [clientId: GOOGLE_ANALYTICS_ID]

    enableIntegration 'Something Enabled', true
    enableIntegration 'Something Disabled', false

    context(
        ip: IP_ADDRESS,
        language: LANGUAGE,
        userAgent: USER_AGENT,
        Intercom: INTERCOM,
        nullable: null
    )
}

4.1.6. Tracking Events

You can track user events with additional properties.

See the documentation for the further information.

Java
service.track(USER_ID, EVENT, b -> b
    .properties("category", CATEGORY)
    .properties("section", SECTION)
    .properties("nullable", null)
    .timestamp(now)
    .anonymousId(ANONYMOUS_ID)
    .messageId(MESSAGE_ID)
    .integrationOptions("Google Analytics", "clientId", GOOGLE_ANALYTICS_ID)
    .enableIntegration("Something Enabled", true)
    .enableIntegration("Something Disabled", false)
    .context("ip", IP_ADDRESS)
    .context("language", LANGUAGE)
    .context("userAgent", USER_AGENT)
    .context("Intercom", INTERCOM)
    .context("nullable", null)
);
Groovy
service.track(USER_ID, EVENT) {
    properties(
        category: CATEGORY,
        section : SECTION,
        nullable: null
    )

    timestamp INSTANT_NOW

    anonymousId ANONYMOUS_ID

    integrationOptions 'Google Analytics', [clientId: GOOGLE_ANALYTICS_ID]

    enableIntegration 'Something Enabled', true
    enableIntegration 'Something Disabled', false

    context(
        ip: IP_ADDRESS,
        language: LANGUAGE,
        userAgent: USER_AGENT,
        Intercom: INTERCOM,
        nullable: null
    )
}

4.2. Customization

You can declare message transformers and interceptors. They are only taken into account when the real implementation is used. They are ignored when no-op implementation is used.

4.2.1. Message Transformation

You can declare MessageTransformer beans to change the payload before sending. Here is the example of transformer which adds default value if not present:

Java
import com.segment.analytics.MessageTransformer;
import com.segment.analytics.messages.Message;
import com.segment.analytics.messages.MessageBuilder;

import jakarta.inject.Singleton;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Sets the default context value if missing.
 */
@Singleton
public class DefaultContextMessageTransformer implements MessageTransformer {

    @Override
    @SuppressWarnings("unchecked")
    public boolean transform(MessageBuilder builder) {
        Message message = builder.build();

        Map<String, ?> context = message.context();

        if (context == null) {
            builder.context(Collections.singletonMap("FromTransformer", "Value"));
            return true;
        }

        if (!context.containsKey("FromTransformer")) {
            Map<String, Object> newContext = new LinkedHashMap<>(context);
            newContext.put("FromTransformer", "Value");
            builder.context(newContext);
        }

        return true;


    }

}

4.2.2. Message Interceptors

You can declare MessageInterceptor beans to intercept sending of the messages. Here is an example of the interceptor which holds the latest message sent:

Java
import com.segment.analytics.MessageInterceptor;
import com.segment.analytics.messages.Message;

import jakarta.inject.Singleton;

/**
 * Keeps the reference to the last message.
 */
@Singleton
public class LastMessageHolder implements MessageInterceptor {

    private Message lastMessage;

    public Message getLastMessage() {
        return lastMessage;
    }

    @Override
    public Message intercept(Message message) {
        this.lastMessage = message;
        return message;
    }

}

5. Bugs

To report any bug, please, use the project issues section on GitHub.