Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Niko/android to new template #550

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/data-management/metrics/simple-metric.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ where fact_timestamp >= assignment_timestamp + X days
and assignment_timestamp < current_date - X days
```

Additionally, a maximum number of days (Y) can be set on the retention period by enabling "add a timeframe to aggregate". When this is enabled, the aggregation will include events by subjects after the minimum number of days defined by the retention period (>=X) and before the max timeframe to aggregate (<Y).
Additionally, a maximum number of days (Y) can be set on the retention period by enabling "add a timeframe to aggregate". When this is enabled, the aggregation will include events by subjects after the minimum number of days defined by the retention period (>=X) and before the max timeframe to aggregate (`<Y`).


#### Conversion

Conversion metrics measure the proportion of entities with at least one fact event within a fixed number of days (X) from experiment assignment. For example, a 7-day conversion metric would measure the proportion of users who sign up for a free trial within 7 days of being assigned to the experiment.
Conversion metrics measure the proportion of entities with at least one fact event within a fixed number of days (`X`) from experiment assignment. For example, a 7-day conversion metric would measure the proportion of users who sign up for a free trial within 7 days of being assigned to the experiment.

$\frac{\text{Number of entities with a non-NULL fact within X days}}{\text{Number of unique entities assigned}}$

Expand Down
2 changes: 1 addition & 1 deletion docs/feature-flagging/concepts/audiences.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Audiences allow you to easily define reusable targeting criteria such that you d
![Audience page](/img/feature-flagging/audiences/audience-overview.png)

## Creating an Audience
In the Configuration section, click the "Create" button and select "Audience". Input a title, description (optional), and the [targeting rules](/feature-flagging/concepts/targeting.md).
In the Configuration section, click the "Create" button and select "Audience". Input a title, description (optional), and the [targeting rules](/feature-flagging/concepts/targeting).

![Creating an Audience](/img/feature-flagging/audiences/create-audience.png)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Each rule may have multiple conditions. The rule is only satisfied if all the co

| Operator | Attribute Type | Meaning |
| :----------------------------------------------------------------------------------------- | :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| greater than (>), less than (<), greater than or equal to (>=), less than or equal to (<=) | number, SemVer | Numeric comparison |
| greater than (`>`), less than (`<`), greater than or equal to (`>=`), less than or equal to (`<=`) | number, SemVer | Numeric comparison |
| matches regex | string | Regular expression match |
| one of / not one of | string, number, boolean | Is one of (or not one of) an array of strings. Non-string inputs (number and boolean) are cast to string before performing the comparison. Comparisons are case-sensitive. |

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/marketing/integrating-with-shopify.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ You can use JavaScript to initialize the SDK and check the status of the feature
- Replace `"<YOUR-SDK-KEY>"` with the [SDK key](/sdks/sdk-keys/) you created in Eppo.
- Replace `"<YOUR-FLAG-KEY>"` with the specific [flag key](/feature-flag-quickstart/#create-a-flag) you configured in Eppo for the feature.
- Replace `"<YOUR-SUBJECT-KEY>"` with the id you are using to randomize users. This can be a cookie id, device id, or an id from your analytics platform such as Heap or Rudderstack to name a few. We encourage our customers to keep this id consistent to ensure that bucketing remains consistent. If you will randomizing users who are logged out, see our guidance here on [Subject Keys in a Pre-Authenticated Experiment](/guides/engineering/preauth-experiments/).
- The Eppo client stores your flag configuration locally; it remains available for as many calls, flags and users as you need. You can refresh the cached configuration as often as you need to update flags by setting the `intervalmaxCacheAgeSeconds`. Shopify Classic is not a single-page app. You do not need to re-instantiate the client for every page, but by refreshing the local client, you keep each new page load up-to-date with your configuration. In this example we have arbitrarily set `intervalmaxCacheAgeSeconds` to `180` seconds, which will wait 180 seconds before refreshing the Eppo configuration from our CDN. Feel free to update this interval whatever time frame makes sense for your use case. Read more about the advanced initialization options [here](/sdks/client-sdks/javascript/initialization).
- The Eppo client stores your flag configuration locally; it remains available for as many calls, flags and users as you need. You can refresh the cached configuration as often as you need to update flags by setting the `intervalmaxCacheAgeSeconds`. Shopify Classic is not a single-page app. You do not need to re-instantiate the client for every page, but by refreshing the local client, you keep each new page load up-to-date with your configuration. In this example we have arbitrarily set `intervalmaxCacheAgeSeconds` to `180` seconds, which will wait 180 seconds before refreshing the Eppo configuration from our CDN. Feel free to update this interval whatever time frame makes sense for your use case. Read more about the advanced initialization options [here](/sdks/client-sdks/javascript/Initialization).

### **Shopify Hydrogen (React-Based Storefront)**

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/migrations/optimizely-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
});
```

*[Eppo](/sdks/client-sdks/javascript/initialization):*
*[Eppo](/sdks/client-sdks/javascript/Initialization):*

```tsx
await init({
Expand Down
16 changes: 0 additions & 16 deletions docs/reference/webhook.md

This file was deleted.

88 changes: 88 additions & 0 deletions docs/reference/webhook.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Experiment Update Webhook

Webhooks let your integrations take action in response to events that occur in Eppo. The Experiment Update Webhook is a good solution when a custom application needs to display or take action on the most up to date state of an experiment.

## Webhook Events
The webhook sends four types of experiment update events. If you only want to take action based on certain types of events, you can filter to just the events you are interested in subscribing to based on their event type in the request body.

### Experiment Metric Updated
**Triggers when:**
- Metric is added or removed
- Metric collection is added or removed

**Request body:**

```json
{
"event": "experiment.metric.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>"
},
"signature": "<signature>"
}
```

### Experiment Configuration Updated
**Triggers when:**
- User edits any configuration

**Request body:**

```json
{
"event": "experiment.configuration.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>"
},
"signature": "<signature>"
}
```

### Experiment Status Updated
**Triggers when:**
- Experiment's status changes

**Request body:**

```json
{
"event": "experiment.status.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>"
},
"signature": "<signature>"
}
```

### Experiment Calculated Metrics Updated
**Triggers when:**
- Data pipeline run irrespective of success or failure and mode of trigger manual or scheduled


**Request body:**

```json
{
"event": "experiment.calculated_metrics.updated",
"data": {
"experiment_id": "<experiment_id>",
"experiment_key": "<experiment_key>",
"meta_data": {
"status": "<success | failure>",
"is_manual_refresh": "<boolean>",
"is_data_updated": "<boolean>",
"time_taken_seconds": "<number>",
"is_traffic_imbalance": "<boolean>",
"assignments_scan_start_date": "<date>",
"assignments_scan_end_date": "<date>"
}
},
"signature": "<signature>"
}
```

## Configuring the webhook
To use the webhook, you first need to setup a URL on your side to receive the webhook payload. Once that is done, contact [Eppo support](emailto:[email protected]) to set and enable the webhook.
4 changes: 4 additions & 0 deletions docs/sdks/client-sdks/android/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Android",
"position": 2
}
178 changes: 178 additions & 0 deletions docs/sdks/client-sdks/android/assignments.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
---
title: Assignments
sidebar_position: 4
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import ApiOptionRef from '@site/src/components/ApiOptionRef';

Assignments are the mechanism through which a given [Subject](/sdks/sdk-features/subjects) is assigned to a variation for a feature flag, experiment, or bandit.

Currently, the Eppo SDK supports the following assignment types:

- String
- Boolean
- JSON
- Numeric (Integer and Double)

## How Assignments Work

The SDK periodically retrieves configuration rules from the Eppo server that define how subjects should be allocated to variants. When you call an assignment function, the SDK evaluates these rules locally without making additional network requests.

Each assignment requires:

- **Flag Key**: Identifies which set of configuration rules to use
- **Subject Key**: A unique identifier for the subject (usually a user ID)
- **Subject Attributes**: Optional key-value pairs containing additional information used for rule evaluation
- **Default Value**: Fallback value if assignment fails or rules don't match

## String Assignments

String assignments return a string value that is set as the variation for the experiment. String flags are the most common type of flags and are useful for both A/B/n tests and advanced targeting use cases.

```java
import cloud.eppo.android.EppoClient;

EppoClient eppoClient = EppoClient.getInstance();

String flagKey = "new-landing-page";
String subjectKey = getUserId() || "anonymous";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can't use the || operator like this in Java (unlike Javascript).
You have to do instead:

String subjectKey = getUserId() != null ? getUserId() : "anonymous";

Map<String, Object> subjectAttributes = new HashMap<>();
subjectAttributes.put("country", "US");
subjectAttributes.put("device", "android");
String defaultValue = "control";

String variation = eppoClient.getStringAssignment(
flagKey,
subjectKey,
subjectAttributes,
defaultValue
);

// Use the variant value to determine which component to render
if (variation.equals("version-a")) {
showVersionA();
} else if (variation.equals("version-b")) {
showVersionB();
} else {
showControl();
}
```

## Boolean Assignments

Boolean flags support simple on/off toggles. They're useful for simple, binary feature switches like blue/green deployments or enabling/disabling a new feature.

```java
boolean isEnabled = eppoClient.getBooleanAssignment(
"new-feature",
subjectKey,
subjectAttributes,
false // default value
);

if (isEnabled) {
showNewFeature();
} else {
showExistingFeature();
}
```

## Numeric Assignments

The SDK supports both integer and double numeric assignments. These are useful for testing different numeric values like prices, counts, or thresholds.

```java
// Integer assignment
int itemCount = eppoClient.getIntegerAssignment(
"items-per-page",
subjectKey,
subjectAttributes,
10 // default value
);

// Double assignment
double price = eppoClient.getDoubleAssignment(
"subscription-price",
subjectKey,
subjectAttributes,
9.99 // default value
);
```

## JSON Assignments

JSON assignments allow for complex configuration objects. They're useful for testing multiple related values together.

```java
import org.json.JSONObject;

JSONObject defaultConfig = new JSONObject();
defaultConfig.put("color", "#FF0000");
defaultConfig.put("fontSize", 14);
defaultConfig.put("fontFamily", "Roboto");

JSONObject config = eppoClient.getJSONAssignment(
"ui-config",
subjectKey,
subjectAttributes,
defaultConfig
);

// Use the configuration
String color = config.getString("color");
int fontSize = config.getInt("fontSize");
String fontFamily = config.getString("fontFamily");
```

## Assignment Logging

When using the SDK for experiments (rather than just feature flags), you'll need to log assignments to analyze the results. The SDK provides a flexible logging system that can integrate with any analytics or data warehouse solution.

### Logging Setup

Configure assignment logging during SDK initialization:

```java
AssignmentLogger logger = new AssignmentLogger() {
@Override
public void logAssignment(Assignment assignment) {
// Log assignment to your analytics system
analytics.track("Eppo Experiment Assignment",
new Properties()
.putValue("experiment", assignment.getExperiment())
.putValue("variation", assignment.getVariation())
.putValue("subject", assignment.getSubject())
.putValue("timestamp", assignment.getTimestamp())
);
}
};

EppoClient eppoClient = new EppoClient.Builder("YOUR_SDK_KEY", getApplication())
.assignmentLogger(logger)
.buildAndInit();
```

:::note
More details about logging and examples can be found in the [event logging](/sdks/event-logging/) page.
:::

## Debugging Assignments

You may encounter situations where a flag assignment produces unexpected values. The SDK provides debugging functions to help understand how assignments are being made:

```java
import cloud.eppo.android.dto.AssignmentDebugInfo;

AssignmentDebugInfo debugInfo = eppoClient.getAssignmentDebugInfo(
flagKey,
subjectKey,
subjectAttributes
);

// Log debug information
Log.d("Eppo", "Assignment debug info: " + debugInfo.toString());
```

For more information about debugging, see the [debugging documentation](/sdks/sdk-features/debugging-flag-assignment).
Loading