Feature engagement

Track feature usage in your application using the Atono SDK.

The Atono SDK lets you track how users interact with a feature by recording usage events and sending them to Atono. Each usage event is associated with a specific story, so you can see how the feature behind that story is being adopted.

Usage data appears in the Feature engagement graph on the story and across all tracked features on the Engagement page.

The Web and React SDKs require version 1.1.0 or later for usage tracking. For installation and initialization instructions, see Get started with the Atono SDK.



Record usage

Call record() when someone interacts with the feature you want to track. The usage key is the story ID from Atono, such as STORY-67. You can copy the story ID from the story header.

Each time record() is called, the SDK records a timestamped usage event associated with the current environment and, when available, the customer and location. The story’s Feature engagement graph updates automatically.

Web

In this example, button represents a reference to a specific element in the application:

const usage = atono.getUsageReporter();

button.addEventListener('click', () => {
    usage.record('STORY-67');
});

Replace STORY-67 with the ID of the story associated with the feature.

React

Use the useUsageReporter() hook in a component inside <AtonoProvider>:

import { useUsageReporter } from '@atono-io/react-sdk';

function TryButton() {
    const { record } = useUsageReporter();

    return (
        <button onClick={() => record('STORY-67')}>
            Try the feature
        </button>
    );
}

Replace STORY-67 with the ID of the story associated with the feature.

Java

Call record() on the usage reporter when someone uses the feature you want to track. The usage key identifies the story associated with the feature, such as STORY-67.

atono.getUsageReporter().record("STORY-67");

Replace STORY-67 with the ID of the story associated with the feature.

Usage events are published asynchronously, so calling record() doesn’t block while the SDK communicates with Atono.

Node.js

Call record() on the usage reporter when someone uses the feature you want to track. Pass the ID of the story associated with the feature, such as STORY-67.

atono.getUsageReporter().record('STORY-67');

Replace STORY-67 with the ID of the story associated with the feature.

Usage events are published asynchronously, so calling record() doesn’t block while the SDK communicates with Atono.


Provide customer and location context

Context lets Atono associate usage with a particular customer or location.

Customer context is optional. If an event doesn’t include a customer value, its usage appears as Unknown in the Feature engagement graph.

How you provide context depends on the SDK.

Web

The Web SDK detects location automatically from the user’s IP address.

Set customer context after initializing the SDK:

await atono.setContext({
    customer: 'your-customer-id'
});

Replace your-customer-id with the customer identifier used in your application.

Set the environment key once per session. If the active customer changes, update the context before calling record() so the event includes the latest value.

React

The React SDK detects location automatically from the user’s IP address.

Provide customer context through <AtonoProvider>:

import { AtonoProvider } from '@atono-io/react-sdk';

function RootComponent() {
    const evaluationContext = {
        customer: 'your-customer-id'
    };

    return (
        <AtonoProvider
            environmentKey="<your-environment-key>"
            evaluationContext={evaluationContext}
        >
            <App />
        </AtonoProvider>
    );
}

Replace your-customer-id with the customer identifier used in your application.

Keep the environment key fixed for the session. If the active customer changes, update the context instead of remounting <AtonoProvider>.

Java

The Java SDK doesn’t store evaluation context globally. When a usage event is recorded for a customer or a location, create context for the current request and pass it with the usage record:

import io.atono.sdk.context.EvaluationContext;

var context = EvaluationContext.builder()
    .customer("your-customer-id")
    .location(atono.getLocationProvider().fromClientIp(clientIp))
    .build();

boolean isEnabled = atono.getUsageReporter().record(
    "STORY-67",
    context
);

Replace:

  • STORY-67 with the story id in Atono
  • your-customer-id with the customer identifier used in your application
  • clientIp with the client’s IP address for the current request

Your application is responsible for identifying the appropriate customer and client IP address for the current request. How you manage evaluation context depends on your application architecture. For example, you might cache it for a session or create it for each request.

Pass the client’s IP address, not the IP address of the application server.

The location provider supports IPv4 and IPv6 addresses. If it can’t determine a location from the supplied IP address, the SDK continues evaluating the flag without location context.

Node.js

The Node.js SDK doesn’t store evaluation context globally. When a usage event is recorded for a customer or a location add the evaluation context to the usage record call:

atono.getUsageReporter().record(
    'STORY-67',
    {
      customer: 'your-customer-id',
      location: atono.getLocationService().fromClientIp(clientIp)
    }
);

Replace:

  • STORY-67 with the story id in Atono
  • your-customer-id with the customer identifier used in your application
  • clientIp with the client’s IP address for the current request

Your application is responsible for identifying the appropriate customer and client IP address for the current request. How you manage evaluation context depends on your application architecture. For example, you might cache it for a session or create it for each request.

Pass the client’s IP address, not the IP address of the application server.

The location provider supports IPv4 and IPv6 addresses. If it can’t determine a location from the supplied IP address, the SDK continues evaluating the flag without location context.


Alternative: Atono Chrome extension

For features used in a browser, you can use the Atono Chrome extension to capture user interactions and associate them with stories instead of adding tracking calls to your code. This approach is useful for product managers or QA who want to map usage without adding new tracking calls to the application code.

The Web or React SDK must still be installed and initialized in the browser. For details, see Map clicks for usage tracking.

The Atono Chrome extension can’t capture actions that occur only in server-side Java code. To track those actions, use the Java SDK and call record() in your application.



Troubleshooting

Customer not showing in the graph?

Make sure customer is included in the SDK context before calling record().

Usage events without a customer value appear as Unknown in the graph.

For React, avoid changing the environment key or remounting the <AtonoProvider> during renders. Update the context instead.

For Java and NodeJs, make sure the context passed to record() includes the appropriate customer for the current request.

Location not showing or seems wrong?

For the Web and React SDKs, location is detected automatically from the user’s IP address. VPNs and proxies can affect the detected location.

For Java and NodeJs, make sure you pass the client’s IP address to the location provider. If the SDK can’t determine a location from the address, it records the event without location context.

Context shows up intermittently?

For the Web and React SDKs, this can happen if the SDK is reinitialized during a session. Keep the environment key fixed and set customer context before calling record().

For Java and NodeJs, make sure the appropriate context is passed with every usage event.

No data at all?

Check the following:

  • The appropriate Atono SDK is installed and initialized
  • For the Web and React SDKs, version 1.1.0 or later is installed
  • A valid story ID is passed to record(), such as STORY-67
  • The correct environment key is being used
  • For Java and NodeJs, context is passed with the usage event
  • The story is assigned to a team
  • The story is in a workflow step categorized as In progress or Done
  • The selected date range isn’t excluding recent activity
  • Filters aren’t hiding expected data

Did this page help you?