Skip to content

Commit

Permalink
feat: Amplitude Experiment - add support for feature flags (#4078)
Browse files Browse the repository at this point in the history
  • Loading branch information
tyiuhc authored Jan 15, 2025
1 parent 73a6de2 commit 17a3ba8
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 291 deletions.
2 changes: 1 addition & 1 deletion apps/amplitude-experiment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Run
yarn install && yarn start
```

To test locally, create an app definition that points to `localhost:3000` for the App URL and register the `App configuration screen`, `Entry sidebar`, and `Entry editor` locations.
To test locally, create an app definition that points to `localhost:5173` for the App URL and register the `App configuration screen`, `Entry sidebar`, and `Entry editor` locations.

## [Privacy Policy](https://amplitude.com/privacy)

Expand Down
4 changes: 4 additions & 0 deletions apps/amplitude-experiment/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
"name": "amplitude-contentful",
"version": "1.0.6",
"private": true,
"engines": {
"node": ">=18.0.0 < 20.0.0",
"npm": ">= 9.0.0 < 11.0.0"
},
"dependencies": {
"@contentful/app-sdk": "^4.29.1",
"@contentful/f36-components": "4.70.0",
Expand Down
68 changes: 39 additions & 29 deletions apps/amplitude-experiment/src/contexts/ExperimentContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createContext, useEffect, useMemo, useState } from "react";
import { AmplitudeExperimentApi } from "../utils/amplitude";
import { useSDK } from "@contentful/react-apps-toolkit";
import { createContext, useEffect, useMemo, useState } from 'react';
import { AmplitudeExperimentApi } from '../utils/amplitude';
import { useSDK } from '@contentful/react-apps-toolkit';

export interface Variant {
[key: string]: string;
Expand All @@ -15,6 +15,7 @@ export interface TargetSegmentCondition {
type: string;
values: Array<string>;
}

export interface TargetSegment {
bucketingKey: string;
conditions: Array<TargetSegmentCondition>;
Expand All @@ -24,9 +25,9 @@ export interface TargetSegment {
}

export declare enum ExperimentDecision {
ROLLOUT = "rollout",
ROLLBACK = "rollback",
CONTINUE_RUNNING = "continue-running",
ROLLOUT = 'rollout',
ROLLBACK = 'rollback',
CONTINUE_RUNNING = 'continue-running',
}

export interface Experiment {
Expand All @@ -53,8 +54,31 @@ export interface Experiment {
rolloutWeights: RolloutWeights;
}

export interface Flag {
bucketingKey: string;
bucketingSalt: string;
bucketingUnit: string;
decision: ExperimentDecision | null;
deleted: boolean;
description: string;
evaluationMode: string;
enabled: boolean;
id: string;
projectId: string;
deployments: Array<string>;
key: string;
name: string;
variants: Array<Variant>;
targetSegments: Array<TargetSegment>;
rolloutPercentage: number;
stickyBucketing: boolean;
tags: Array<string>;
rolledOutVariant: string | null; // variant key
rolloutWeights: RolloutWeights;
}

interface ExperimentContextProps {
experiments: Array<Experiment>;
experiments: Array<Experiment | Flag>;
loading: boolean;
amplitudeExperimentApi: AmplitudeExperimentApi | null;
}
Expand All @@ -65,40 +89,26 @@ export const ExperimentContext = createContext<ExperimentContextProps>({
amplitudeExperimentApi: null,
});

export const ExperimentProvider = ({
children,
}: {
children: React.ReactElement;
}) => {
export const ExperimentProvider = ({ children }: { children: React.ReactElement }) => {
const sdk = useSDK();
const [experiments, setExperiments] = useState<Experiment[]>([]);
const [experiments, setExperiments] = useState<(Experiment | Flag)[]>([]);
const [loading, setLoading] = useState<boolean>(false);
const amplitudeExperimentApi = useMemo(
() =>
new AmplitudeExperimentApi(
sdk.parameters.installation.managementApiKey,
sdk.parameters.installation.datacenter
),
[
sdk.parameters.installation.managementApiKey,
sdk.parameters.installation.datacenter,
]
() => new AmplitudeExperimentApi(sdk.parameters.installation.managementApiKey, sdk.parameters.installation.datacenter),
[sdk.parameters.installation.managementApiKey, sdk.parameters.installation.datacenter]
);

useEffect(() => {
const fetchExperiments = async () => {
setLoading(true);
const experiments = await amplitudeExperimentApi.listAllExperiments();
return experiments;
const experiments = await amplitudeExperimentApi.listAllResources(true);
const flags = await amplitudeExperimentApi.listAllResources();
return [...experiments, ...flags];
};
fetchExperiments().then((experiments) => {
setExperiments(experiments);
setLoading(false);
});
}, [amplitudeExperimentApi]);
return (
<ExperimentContext.Provider value={{ experiments, loading, amplitudeExperimentApi }}>
{children}
</ExperimentContext.Provider>
);
return <ExperimentContext.Provider value={{ experiments, loading, amplitudeExperimentApi }}>{children}</ExperimentContext.Provider>;
};
Loading

0 comments on commit 17a3ba8

Please sign in to comment.