# Live Events Source: https://docs.flagsync.com/events/live-tail View real-time impressions and events in FlagSync with Live Event Tail. ## What Is Live Event Tail? Live Event Tail lets you watch impressions and events as they happen, available on Team and Pro plans. It tracks: * **Events**: Generated when you call `client.track()`—user actions like clicks or purchases. * **Impressions**: Logged automatically with every `client.flag()` call—showing which flag variant users see. ## How to Access ### View All Live Events and Impressions * Go to the [Events Dashboard](https://www.flagsync.com/dashboard/events/) to see real-time activity across your environment. Live Events Dashboard showing tracked events ### View Live Impressions for a Flag * Navigate to the [Flags Dashboard](https://www.flagsync.com/dashboard/flags/). * Select your feature flag (e.g., `signup-cta`), then click the "Live Tail" tab. ## Why It Matters * **Developers**: Debug issues or verify `track()` and `flag()` calls instantly. * **Product Managers**: Monitor feature performance live—e.g., how `Join Now` impressions convert. ## Next Steps * Learn about [Events](/events/overview) and [Impressions](/impressions/overview). * Start tracking in [Quickstart: Send Events](/quickstarts/events). * Set up flags in [Quickstart: Integrate the SDK](/quickstarts/sdk). # Overview Source: https://docs.flagsync.com/events/overview Track user interactions in FlagSync to measure feature impact and drive experiments. ## What Are Events? Events log user actions—like clicks, sign-ups, or purchases—in your app. You send them manually via the SDK’s `track()` function to capture behavior tied to features, providing raw data for metrics and experiments that help developers and product teams assess rollout effects. ## How Events Work Call `track()` with an `eventKey` to name the event, and optionally an `eventValue` (numeric) or `properties` (key-value pairs) for extra detail: ```typescript Client-side theme={null} client.track( eventKey: string, eventValue?: number | null, properties?: Record | null ); ``` ```typescript Server-side theme={null} client.track( context: FsUserContext, // User context required eventKey: string, eventValue?: number | null, properties?: Record | null ); ``` Once submitted, Events appear automatically in the FlagSync dashboard—no predefinition needed. * **Use Cases**: Track anything from button clicks to performance stats—whatever matters to your app. ## Events in Action Events fuel FlagSync’s power: Watch them live in [Live Events](/events/live-tail). Build conversion rates or aggregates in [Metrics](/metrics/overview). Link them to flags in [Experiments](/experiments/overview) to test hypotheses. Drop `track()` anywhere in your code—events auto-sync to FlagSync for analysis. Use events to spot trends or prove feature impact—no coding required to view results. ## Next Steps * Start tracking with [Tracking Events](/events/tracking). * Aggregate events in [Metrics](/metrics/overview). * Test with flags in [Experiments](/experiments/overview). # Tracking Events Source: https://docs.flagsync.com/events/tracking Capture user actions in FlagSync with Numeric and Property events. ## How Are Events Tracked? Manually track user actions in FlagSync via the `track()` function, providing the core data that all [Metrics](/metrics/overview) rely on for analysis. ```typescript theme={null} client.track( eventKey: string, eventValue?: number | null, properties?: Record | null ); ``` ## Tracking Event Types There are two types of events: Captures measurable data like time or counts. Captures rich context like purchase details. ### Numeric Events Use `eventValue` to capture measurable data like time or counts for [Numeric Metrics](/metrics-numeric/overview): ```typescript theme={null} // Track page load time in seconds client.track('page_load_time', 1.42); ``` Perfect for metrics like "Average Page Load Time"—tracks quantifiable outcomes for analysis. Test if a feature slows or improves your app—send this event, then review the average in Metrics. A developer might track load times across a new UI—e.g., 1.42s—to ensure performance holds. ### Property Events Use `properties` to capture rich context like purchase details for detailed [Numeric Metrics](/metrics-numeric/overview): ```typescript theme={null} const purchase = { productId: '0x123', price: 49.99, discount: 0.20, isReturningUser: true, }; client.track('purchase_event', null, purchase); ``` Allows the creation of multiple [Numeric Metrics](/metrics-numeric/overview) (e.g., "Average Purchase Price" from `price`, "Discount Usage" from `discount`) from one `purchase_event`. Test if a feature increases purchase amounts or targets returning users—analyze in [Metrics](/metrics/overview). Track a `purchase_event` to check if a 20% discount boosts \$49.99 purchases or engages returning buyers. Why not just use `price` as the `eventValue`? Properties let you track one `purchase_event` and create separate metrics for `price`, `discount`, or other keys—more flexibility than a single number. See [Metric Examples](/metrics-numeric/examples) for more detail. ## Best Practices * **Name Clearly**: Use descriptive event keys (e.g., `signup-cta-click`) to match metrics. * **Limit Data**: Include only relevant properties (e.g., `price`, `discount`) to avoid clutter. * **Validate Early**: Check events in [Live Events](/events/live-tail) before defining metrics. ## Next Steps * Learn basics in [Events Overview](/events/overview). * Explore live tracking in [Live Events](/events/live-tail). * Define metrics in [Quickstart: Define Metrics](/quickstarts/metrics) or explore in [Metrics](/metrics/overview). # Creating Experiments Source: https://docs.flagsync.com/experiments/create-experiment Set up and configure experiments in FlagSync to test feature variations. ## Experiment Creation Set up an experiment in FlagSync to test feature flag variants against metrics. This process integrates [Feature Flags](/flags/overview), [Events](/events/overview), and [Metrics](/metrics/overview) to evaluate performance and optimize your product with data. Define a name (e.g., "Button Text Test") and hypothesis (e.g., "Changing 'Buy Now' to 'Complete Purchase' will boost conversions due to clarity"). Experiment details form A specific hypothesis aids result interpretation. Pick existing [Metrics](/metrics/overview) (e.g., conversion rates, totals) or create new ones, to measure success. Experiment metrics form Select or create a flag with variants to test (e.g., "Buy Now" vs. "Add to Cart"). Experiment flag form Pick the control variant (e.g., current "0% discount") to compare against others. Experiment baseline form Typically the current production value, or best-performing variant. Allocate percentages to each variant (e.g., 50% baseline, 50% new)—must total 100%. Experiment rollout form Changing traffic or variants starts a new experiment iteration for data integrity. * Save and start the experiment to collect data * Once active, FlagSync tracks impressions and events, aggregating metrics to compare variants. Run for a fixed time (e.g., two weeks) or until significant statistical results are achieved. FlagSync locks linked flags and metrics while running. ## Next Steps Get started with a guided flow in [Quickstart: Overview](/quickstarts/overview), then: * Learn about metrics in [Metrics](/metrics/overview). * Monitor results in [Monitoring and Analysis](/experiments/monitoring). # Monitoring and Analysis Source: https://docs.flagsync.com/experiments/monitoring Evaluate experiment performance in FlagSync with real-time and historical data. ## Monitoring Your Experiment Monitoring and analysis in FlagSync let you assess how feature flag variants perform during and after an experiment. By reviewing impressions, events, and metrics, teams can determine which variants optimize goals like conversions or user engagement, refining strategies with data-driven insights. ## Data Sources

Automatically logged when `client.flag()` serves a variant.


e.g., tracking which users see "Join Now" or "Register".

Captured via `client.track()` in your code.


e.g., logging sign-ups or purchases tied to those variants.

Aggregates impressions and events into conversion rates or numeric values for analysis.


e.g., average spend

## Interpreting Results

Compare the percentage of users acting after seeing a flag variant (events ÷ impressions).


e.g., if "Sign Up" has 25% conversions and "Register" has 15%, "Sign Up" may outperform.

Assess aggregated values per user—e.g., higher purchase amounts with a discount.


e.g., if no discount averages \$50 and a 10% discount averages \$60, the 10% variant wins.
Use these insights to adopt the winning variant or inform the next experiment iteration. ### Real-World Example Here’s how the `Register Conversion` experiment plays out in a live FlagSync experiment, testing if new button copy increases sign-up conversions: Flag creation form filled out It's clear that "Join Now" has resulted in more conversions. ## Accessing Experiment Data * **Live Monitoring**: View real-time results on the [Experiments Dashboard](https://www.flagsync.com/dashboard/experiments/) while the experiment runs. * **Past Iterations**: For completed experiments, go to the specific experiment page and select the "Previous Iterations" tab to review historical data. ## Next Steps Decided on a winner? * Keep the top variant live in [Feature Flags](/flags/overview). * Refine with a new experiment in [Create an Experiment](/experiments/create-experiment). # Overview Source: https://docs.flagsync.com/experiments/overview Test feature variations to optimize your product with data-driven insights. ## What Are Experiments? Experiments (or A/B/n testing) compare multiple feature variants (e.g., different button texts, layouts, or price discounts) and determine which performs best against goals like conversion rates, user engagement, or page time. By rolling out variants to user segments and measuring real-world results, teams gain data-driven insights to refine product design and user experience. ## Why Experiments Matter Validate changes with real user data, not guesses. Metrics cut through opinions with clear numbers. Test, tweak, and improve continuously. ## What Is a FlagSync Experiment? A FlagSync experiment integrates [Feature Flags](/flags/overview), [Events](/events/overview), and [Metrics](/metrics/overview) into a unified testing framework. It tests flag variants (e.g., "baseline" vs. "new design") against one or more metrics by correlating: * **Impressions**: What users see * **Events**: What users do This evaluates if a variant outperforms, underperforms, or matches the baseline—e.g., does "Join Now" increase conversions over "Register"?

**Impressions**: Automatically logged when `client.flag()` serves a variant.

**Events**: Manually tracked with `client.track()` to capture user actions.

## Best Practices * **Single Hypothesis**: Test one change at a time (e.g., text, not text + color) for clear results. * **Adequate Sample**: Ensure enough users experience each variant to avoid skewed results. * **Clear Goals**: Match metrics to hypothesis objectives (e.g., revenue, engagement) for actionable insights. ## Next Steps Get started with a guided flow in [Quickstart: Overview](/quickstarts/overview), then * Learn about event tracking at [Events](/events/overview). * Set up metrics in [Metrics](/metrics/overview). # Creating Flags Source: https://docs.flagsync.com/flags/create-flag Set up feature flags in FlagSync to manage and test variants. ## Creating a Feature Flag Start by setting up a FlagSync project (try the 14-day free trial, no credit card needed), then create a flag via the Flags dashboard. ### Flag Configuration * **Name**: A human-readable label (e.g., "Signup CTA")—editable later. * **Key**: A unique identifier (e.g., `signup-cta`) for code use. * **Description**: Optional summary of the flag’s purpose. Flag creation form filled out

On/off switches


**Perfect for**:

Enable/disable features

Beta feature toggles

Predefined options


**Common uses**:

Theme: `light-mode`, `dark-mode`

CTA: `Register`, `Join Now`

Numeric values


**Common uses**:

Rate limits: `1000`, `5000`, `10000`

Image quality: `75`, `80`, `100`

Complex objects


**Common uses**:

`{ "layout": "grid", "maxItems": 8 }`

Flag types filled out
Define the variants to serve (e.g., `0.00`, `0.10`, `0.20` for `discount-rate`). Flag variants filled out Set defaults for `discount-rate`: * **Enabled**: `0.20` (20% discount). * **Disabled**: `0.00` (no discount). Flag variants filled out * When the flag is **on**, the **enabled** variant (e.g., `0.20`) is served unless overridden by targeting. * When the flag is **off**, the **disabled** variant (e.g., `0.00`) applies to all users. Click "Create Flag" to save. * Toggle the flag on or off to control its rollout. * Integrate with code via [Quickstart: Integrate the SDK](/quickstarts/sdk).
## Next Steps * Configure targeting in [Targeting and Rollouts](/flags/targeting-and-rollouts). * Run experiments in [Quickstart: Create an Experiment](/quickstarts/experiment). # Overview Source: https://docs.flagsync.com/flags/overview Learn the basics of feature flags in FlagSync for flexible feature management. ## What Are Feature Flags? Feature flags enable teams to toggle features, roll out updates gradually, and run A/B tests without redeploying code. In FlagSync, they power [Experiments](/experiments/overview) and [Metrics](/metrics/overview) by serving variants (e.g., "On" or "Off") to users. ## Why Feature Flags Matter Test features with a subset of users before full release. Compare variants (e.g., "Buy Now" vs. "Add to Cart") in A/B/n tests. Enable or disable features instantly—e.g., during maintenance. Roll out to specific groups or percentages, ensuring stability before full deployment. ## Next Steps * Dive into flag creation in [Creating Flags](/flags/create-flag). * Follow the full guided flow in [Quickstart: Overview](/quickstarts/overview). * Set up tracking for [Events](/events/overview). * Explore [Experiments](/experiments/overview). # Targeting and Rollouts Source: https://docs.flagsync.com/flags/targeting-and-rollouts Control feature flag distribution in FlagSync with targeting and rollouts. ## Targeting Options FlagSync offers flexible ways to roll out feature flags: Serve a variant to everyone. Target specific users or groups using custom attributes. Distribute variants by percentage across users. ### All Users Serve a single variant to every user, ensuring a consistent experience with default settings. This approach relies on: * **Disabled Variant**: Applied when the flag is off, serving as a fallback (e.g., "0% discount" for all). * **Enabled Variant**: Applied when the flag is on, unless overridden by targeting or rollouts (e.g., "20% discount" for all). Defaults provide a safety net—e.g., reverting to "0% discount" during system issues. Default variant settings ### User Segments Target specific users by passing custom attributes via the SDK and defining rules in the dashboard to match those attributes. For example: * **Use Case**: Create a rule to serve a beta feature to "QA Testers" and "PMs" while others see the baseline. * **Implementation**: Provide attributes in the SDK—FlagSync auto-populates the rule creation UI with these attributes for targeting. ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user123', attributes: { jobTitle: 'QA Tester', isVIP: false } } }); ``` In a real app, these values (e.g., `user123`, `QA Tester`) are typically sourced from a user or session object. User segment targeting rule creation Use `key` instead of `custom` to target the unique identifier (e.g., `user123`). ### Percentage Rollouts Distribute variants by percentage to control rollout scope and risk. FlagSync simplifies this with: * **Allocation**: Set splits (e.g., 25% each for four variants)—must total 100%. * **Use Case**: Allow gradual releases—e.g., 10% rollout to test stability. Users are bucketed deterministically, ensuring they receive the same variant consistently during the rollout. Flag creation form filled out ## Next Steps * Create a flag in [Creating Flags](/flags/create-flag). * Learn about metrics in [Metrics: Overview](/metrics/overview). * Run experiments in [Creating Experiment](/experiments/create-experiment). # Introduction Source: https://docs.flagsync.com/getting-started/introduction FlagSync is a simple, powerful platform for feature management and A/B/n testing. Hero Light Hero Dark ## Welcome to FlagSync FlagSync lets teams control rollouts, run experiments, and optimize with confidence using these essentials: Roll out features safely and switch them off instantly if needed. Test variations to find what drives the best results. ## Next Steps * Learn the basics in [Key Concepts](/getting-started/key-concepts). * Start with [Quickstart: Overview](/quickstarts/overview). # Key Concepts Source: https://docs.flagsync.com/getting-started/key-concepts Learn the essentials to kick off your feature management journey. ## FlagSync Basics Master the building blocks of feature control: A feature flag toggles features on or off without redeploying code. Hide `beta-feature` until ready, then enable for testing. Group users by attributes (e.g., location, role) to target flags or experiments. Show `beta-feature` to premium users in Boston. Release features gradually to a fraction of users for safe testing. Enable `beta-feature` for 10% of users, scale up if stable. ## Data and Insights Understand how to measure your features: Record flag evaluations automatically when `flag()` is called. `flag('beta-feature')` logs if a user saw `Enabled`. Track user actions (e.g., clicks) via the SDK’s `track()` function. Log a `purchase_event` to measure `beta-feature`’s impact. Measure flag impact (e.g., conversion rates) using events and impressions. Track `beta-feature`’s click-through rate for engagement. Compare feature variations to measure impact via metrics. Test two `beta-feature` designs and pick the winner by clicks. ## How FlagSync Works FlagSync’s components work together to launch and optimize features—like a new checkout flow—with data-driven confidence: FlagSync lets you roll out, measure, and optimize features in one seamless flow. ## Next Steps * Set up a flag in [Quickstart: Create a Flag](/quickstarts/flag). * Explore [Experiments](/experiments/overview). # Generating Impressions Source: https://docs.flagsync.com/impressions/generating Learn how FlagSync captures impressions to track feature flag exposure. ## How Are Impressions Generated? Impressions are automatically logged each time a flag is evaluated with the `flag` function, capturing the variant served to the user. ```typescript theme={null} client.flag(flagKey: string, defaultValue?: T); ``` ### Example For a flag like `signup-cta` with variants `Join Now`, `Register`, `Sign Up`: ```typescript theme={null} const value = client.flag('signup-cta', 'Register'); console.log(`signup-cta is ${value}`); ``` If **User ABC** is shown `Join Now`, an impression is logged *"User ABC saw `Join Now` for `signup-cta`."* ## Next Steps * Review impressions in [Impressions: Overview](/impressions/overview). * Set up flags in [Quickstart: Integrate the SDK](/quickstarts/sdk). * Explore [Experiments](/experiments/overview) for variant testing. # Overview Source: https://docs.flagsync.com/impressions/overview Track feature flag exposure in FlagSync to measure flag variant impact. ## What Are Impressions? Impressions record which flag variant a user sees—e.g., "Join Now" or "10% discount". They serve as the foundation for measuring feature impact in [Metrics](/metrics/overview) and [Experiments](/experiments/overview). ## Why Impressions Matter Pair with events to calculate conversion rates (e.g., sign-ups per impression). Enable variant comparison—e.g., does "Sign Up" outperform "Register"? Provide exposure data for debugging or rollout validation. ## How to Access * **View All**: See real-time activity on the [Events Dashboard](https://www.flagsync.com/dashboard/events/). Live Events Dashboard showing tracked events * **View for a Flag**: Go to the [Flags Dashboard](https://www.flagsync.com/dashboard/flags/), select your flag (e.g., `signup-cta`), and click "Live Tail". ## Next Steps * Learn more in [Generating Impressions](/impressions/generating). * Set up flags in [Quickstart: Integrate the SDK](/quickstarts/sdk). * Explore [Events](/events/overview) for action tracking. # Examples Source: https://docs.flagsync.com/metrics-numeric/examples See how numeric metrics aggregate event values in FlagSync. ## Examples For a `discount-rate` flag with variants 0%, 20%, and 30%, impressions are logged when users see the applied discount, and events are tracked when they complete a purchase. ```tsx checkout-page.tsx theme={null} // Step 1: Log impression const discountRate = client.flag('discount-rate', 0.00); // Step 2: Track the purchase event const item = { productId: '0x123', price: 50.00, discount: discountRate // 0.3 (30%) }; client.track('purchase_event', null, item); ``` ### Average or Sum Purchase Price Let’s explore how an average or sum metric tracks purchase value for the `discount-rate` flag, testing which variant drives higher spending: Select `purchase_event` and enter `price` as the value field to aggregate: * [Events](/events/overview) auto-populate from `client.track()`. * [Property Events](/events/tracking#property-events) let you derive multiple metrics from one `purchase_event`. Metric event value selection Aggregate by average or sum: Numeric metric aggregation selection See a simulated FlagSync dashboard for the `discount-rate` experiment, testing how discount variants impact average purchase value: Simulated dashboard showing average purchase value for discount-rate variants * **Trend**: The chart shows 30% (pink) leading at \$147 average purchase value, followed by 20% (orange) at \$108, with 0% (blue) at \$83. The 30% variant is the clear winner, increasing average purchase value by 76.4% over the baseline. ## Next Steps * Learn concepts in [Numeric Metrics: Overview](/metrics-numeric/overview). * Explore [Experiments](/experiments/overview). # Overview Source: https://docs.flagsync.com/metrics-numeric/overview Aggregate event values per user in FlagSync to measure feature impact. ## What Are Numeric Metrics? Numeric metrics aggregate event values per user—counting occurrences, summing totals, or averaging amounts—to measure feature impact. Unlike conversion rates, they focus on raw values (e.g., purchase prices, session times). Equal weighting across users in [Experiments](/experiments/overview) is ensured by averaging data per user, preventing heavy user bias from skewing results. ## Aggregation Methods Numeric metrics require an aggregation method to process event data: The average count of events per user. **Example**: Average Purchase Count per User * *If User A makes 3 purchases and User B makes 1, the metric averages to 2.* * *(3 + 1) / 2 = 2* **Use Case**: See if a feature increases purchase frequency (e.g., via a new layout). Returning users raise the average, new users lower it. Other examples: The average number of video plays, help requests per user. The average sum of event values per user. **Example**: Average Total Spend per User * *If User A spends \$100 and User B spends \$50, the metric averages to \$75.* * *(\$100 + \$50) / 2 = \$75* **Use Case**: Test if a feature boosts total spend (e.g., via upselling). Frequent users increase the sum, new users dilute it. Other examples: The average total time spent watching videos, pages visited on your site. The average of per-user event averages. **Example**: Average Purchase Price per User * *If User A’s purchases average \$40 and User B’s average \$60, the metric is \$50.* * *(\$40 + \$60) / 2 = \$50* **Use Case**: Check if a feature changes typical purchase value (e.g., via a discount). The average reflects per-user values—new users’ data can shift it up or down based on their behavior. Other examples: The average time on site per session, items added to the cart. ## Next Steps * See examples in [Examples](/metrics-numeric/overview). * Track events in [Quickstart: Send Events](/quickstarts/events). * Explore [Conversion Rate Metrics](/metrics/conversion-rate). # Conversion Rate Source: https://docs.flagsync.com/metrics/conversion-rate Measure user actions as a percentage of flag exposure in FlagSync. ## What Are Conversion Rate Metrics? Conversion rate metrics measure the percentage of users who perform an action after seeing a flag variant—calculated as: ``` (# of events / # of impressions) = % conversion rate ``` They track how often a specific event (e.g., a `signup-complete`) follows a flag impression, revealing which variants drive behavior in [Experiments](/experiments/overview). ## Example: Sign-Up Conversion Let’s explore how a conversion rate metric tracks sign-ups for the `signup-cta` flag, testing which button text variant (`Join Now`, `Register`, or `Sign Up`) drives the most conversions: Logs an impression each time the `flag()` function gets the text variant: ```jsx theme={null} // landing-page.tsx const value = client.flag('signup-cta', 'Register'); ``` Track the `signup-complete` event when a user signs up: ```typescript theme={null} // register-page.tsx ``` * In an [Experiment](/experiments/overview), FlagSync links these `signup-complete` events to `signup-cta` impressions to calculate conversion rates. * If User ABC sees `Join Now` and later triggers `signup-complete`, FlagSync records it as a successful conversion. **Timing matters**: Only events tied to prior impressions count—FlagSync ensures the user saw the variant before acting, ensuring accurate cause-and-effect. ### Sample Conversion Results Here’s a hypothetical outcome of the `signup-cta` experiment, showing how many users sign up after seeing each variant (`Join Now`, `Register`, `Sign Up`) with 100 users per variant: | Variant | Impressions | Sign Up Completions | Conversion Rate | | -------- | ----------- | ------------------- | --------------- | | Register | 100 | 15 | 15% | | Sign Up | 100 | 25 | 25% | | Join Now | 100 | 35 | 35% | **Insight**: Join Now leads with 35%—it’s the most effective at driving sign-ups. ### Example Dashboard Insights See a simulated FlagSync dashboard for the `signup-cta` experiment, testing how button copy variants (`Join Now`, `Register`, `Sign Up`) impact sign-up conversions over time: Flag creation form filled out * **Trend**: The chart shows `Join Now` (pink) leading over time, followed by `Sign Up` (orange), with `Register` (blue) trailing—confirming our example’s insight. ## Next Steps * Track events in [Quickstart: Send Events](/quickstarts/events). * Define metrics in [Quickstart: Define Metrics](/quickstarts/metrics). * Test in [Quickstart: Create an Experiment](/quickstarts/experiment). * Explore [Numeric Metrics](/metrics-numeric/overview). # Overview Source: https://docs.flagsync.com/metrics/overview Measure feature impact in FlagSync with event-driven metrics. ## What Are Metrics? Metrics show how feature rollouts affect users—like clicks, sign-ups, or purchases—by analyzing events and impressions. They’re essential for pinpointing optimal flag settings and driving data-backed experiments. ## Defining a Metric Metrics start with [Events](/events/overview) you’ve tracked (e.g., `signup-cta-click`). Here’s what defines them: Follow along in the Dashboard, click "+" next to **Metrics** or go to [Create a Metric](https://www.flagsync.com/dashboard/metrics/new/). ### Measurement Type Choose how to analyze data—each type powers experiments differently: Measures the percentage of users acting after seeing a flag (events ÷ impressions). Aggregates event values per user—e.g., counts, sums, or averages. ### Aggregation Method (Numeric Only) For numeric metrics, pick how to process values: * **Count**: Number of events per user (e.g., purchases). * **Sum**: Total value per user (e.g., spend). * **Average**: Average value per event (e.g., price). * See [Numeric Metrics](/metrics-numeric/overview) for details. ### Metric Impact Set the goal—does success mean more or less? This guides how results are interpreted in [Experiments](/experiments/overview): Higher values are better—e.g., more `signup-complete` events for registrations. Lower values are better—e.g., fewer `error-occurred` events for stability. ## Next Steps * Explore types in [Conversion Rate](/metrics/conversion-rate) or [Numeric](/metrics-numeric/overview). * Track events in [Quickstart: Send Events](/quickstarts/events). * Define a metric in [Quickstart: Define Metrics](/quickstarts/metrics). * Test with [Experiments](/experiments/overview). # Send Events Source: https://docs.flagsync.com/quickstarts/events Track user actions in FlagSync to measure feature impact. ## Sending Events Events track user actions like clicks, sign-ups, or purchases. In this third step, we’ll track two events for the `new-feature` flag (from [Quickstart: Set Up a Flag](/quickstarts/flag)) to test if the new layout boosts conversions in an experiment. * `Sign-Up CTA Click` (sign-up clicks within the layout (`Disabled` / `Enabled`) * `Sign-Up Complete` (completed sign-ups). Ensure the SDK is initialized (from [Quickstart: Integrate the SDK](/quickstarts/sdk)): ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'userId_0x123' } }); const client = factory.client(); await client.waitForReady(); ``` Add a `track()` call when users click the CTA: ```tsx React theme={null} ``` ```javascript Vanilla JS theme={null} document .getElementById('signup-btn') .addEventListener('click', () => { client.track('signup-cta-click'); }); ``` Log when users complete registration: ```typescript theme={null} function onSignUpComplete() { client.track('signup-complete'); } ``` * In the Dashboard, Click "+" next to **Metrics** or go to [Create a Metric](https://www.flagsync.com/dashboard/metrics/new/). * Check that `signup-cta-click` and `signup-complete` appear in the "Select Event" dropdown—they’ll auto-populate from these track calls. * You also also watch [Live Events](https://www.flagsync.com/dashboard/events/) from the Dashboard. ## Next Steps Events are flowing—now use them: * Define metrics in [Quickstart: Define Metrics](/quickstarts/metrics). * Learn more in [Events](/events/overview). # Create an Experiment Source: https://docs.flagsync.com/quickstarts/experiment Get up and running with FlagSync Experiments in minutes. ## Creating Your First Experiment Let’s tie it all together—using the `new-feature` flag ([Quickstart: Set Up a Flag](/quickstarts/flag)), its impressions ([Quickstart: Integrate the SDK](/quickstarts/sdk)), events ([Quickstart: Send Events](/quickstarts/events)), and metrics ([Quickstart: Define Metrics](/quickstarts/metrics))—to test if the new layout drives more sign-ups. In the dashboard, click "+" next to **Experiments** or go to [Create an Experiment](https://www.flagsync.com/dashboard/experiments/new/). * **Name**: New Feature Layout Test * **Hypothesis**: The `new-feature` layout will boost user sign-up conversions. Experiment details form Add the metrics from [Quickstart: Define Metrics](/quickstarts/metrics): * `Sign-Up CTA Click`: Tracks sign-up clicks (conversion rate). * `Sign-Up Complete`: Tracks sign-ups (conversion rate). Experiment metrics form Select the `new-feature` flag from [Quickstart: Set Up a Flag](/quickstarts/flag). Experiment flag form Choose `Disabled` as the baseline (the old layout). Experiment baseline form Split traffic across variants: * **Enabled**: 50% * **Disabled**: 50% Percentages must total 100%. Experiment rollout form Click "Create Experiment" to save. From the **New Feature Layout Test** page, click **Start** to begin. ## Next Steps Your experiment is live—now see the results: * Monitor outcomes in [Monitoring and Analysis](/experiments/monitoring). * Review setup in [Events](/quickstarts/events) or [Metrics](/quickstarts/metrics). # Set Up a Flag Source: https://docs.flagsync.com/quickstarts/flag Get up and running with FlagSync in minutes. ## Creating Your First Feature Flag Go to [flagsync.com](https://flagsync.com) and sign in or start your 14-day free trial. In the Dashboard, click "+" next to **Feature Flags** or go to [Create a Flag](https://www.flagsync.com/dashboard/flags/new/). * Name: `New Feature` * Type: `Boolean` * Variants: `Enabled` and `Disabled` Flag creation form filled out Click "Create Flag" to save. From the **New Feature** flag page, switch on the flag to serve the `Enabled` variant. Flag creation form filled out ## Next Steps Your flag is set—now bring it into your app: * Add it with [Quickstart: Integrate the SDK](/quickstarts/sdk). * Explore [User Segments](/flags/targeting-and-rollouts#user-segments) for targeted rollouts. * Try [Percentage Rollouts](/flags/targeting-and-rollouts#percentage-rollouts) for gradual releases. # Define Metrics Source: https://docs.flagsync.com/quickstarts/metrics Aggregate events into insights for FlagSync. ## Defining Metrics Metrics track how features affect users—like clicks or sign-ups—by correlating [events](/quickstarts/events) and [flag impressions](/quickstarts/flag) from users. Let’s create two: * `Sign-Up CTA Click` (sign-up clicks within the layout). * `Sign-Up Complete` (completed sign-ups). We’ll use these in an experiment with the `new-feature` flag (`Enabled`/`Disabled`) to test if the new layout boosts conversions. In the Dashboard, click "+" next to **Metrics** or go to [Create a Metric](https://www.flagsync.com/dashboard/metrics/new/). * **Name**: Enter `Sign-Up CTA Click`. * **Description** (optional): Add “Tracks clicks on the sign-up CTA button.” Metric details form * Select `signup-cta-click` from the dropdown. Metric event form * This auto-populates from SDK calls like: ```typescript theme={null} client.track('signup-cta-click'); ``` Events appear automatically—no need to predefine them. Track what matters in code, and it’ll show up here. Select "Conversion Rate". Metric type form Measures click events vs. impressions (e.g., 100 clicks / 1,000 views = 10%) Select "Increase". Metric type form We want more clicks compared to the baseline (Register). Click "Create Metric" to save. Repeat the process for the `Sign-Up Complete` metric: * **Name**: Enter `Sign-Up Complete`. * **Description** (optional): Add “Tracks sign-up completion.” * **Select Event**: `signup-complete` * **Type**: Conversion Rate * **Impact**: Increase ## Next Steps Metrics are set—now use them: * Test variants in [Quickstart: Create an Experiment](/quickstarts/experiment). * Check results in [Monitoring and Analysis](/experiments/monitoring). * Learn more in [Metrics](/metrics/overview). # Overview Source: https://docs.flagsync.com/quickstarts/overview Walk through FlagSync’s core workflow with these step-by-step guides. ## Get Started with FlagSync These Quickstarts walk you through setting up and testing a feature in FlagSync, from creating a flag to analyzing experiment results. Follow them in order to build a full experiment—or jump to what you need. Create your first feature flag in the dashboard. Add FlagSync to your app with the JavaScript SDK. Track user actions like clicks, sign-ups, or purchases. Measure sign-ups conversions, average purchase value, or other outcomes. Test variants like `Register` vs. `Join Now`. ## Next Steps New to feature flags? Start with [Key Concepts](/getting-started/key-concepts) for the basics. # Integrate the SDK Source: https://docs.flagsync.com/quickstarts/sdk Integrate the FlagSync JavaScript SDK to use your feature flags in code. ## Using the JavaScript SDK With your `new-feature` flag created, bring it into your app with the JavaScript SDK. Check out our [other SDKs](/sdks/overview) for **Node.js**, **Next.js**, **React**, and more. Install the SDK with your preferred package manager: ```bash npm theme={null} npm install @flagsync/js-sdk npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add @flagsync/js-sdk yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add @flagsync/js-sdk pnpm add -D @flagsync/cli ``` Create a client with your SDK key and a unique user identifier, such as user ID or email. ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', // Replace with your SDK key core: { key: 'userId_0x123' // Unique identifier } }); const client = factory.client(); ``` Get your SDK key from your [Workspace settings](https://www.flagsync.com/dashboard/settings/organization/workspaces/) for the target Environment. Ensure the SDK is ready before checking flags: ```typescript theme={null} await client.waitForReady(); console.log('SDK is ready!'); ``` Get the `new-feature` flag’s value: ```typescript theme={null} const value = client.flag('new-feature'); console.log(value); ``` Calling `flag()` automatically logs an impression, tracking which variant each user sees—vital for metrics later. Here's the full example: ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', // Replace with your SDK key core: { key: 'userId_0x123' // Unique identifier } }); const client = factory.client(); await client.waitForReady(); console.log('SDK is ready!'); const value = client.flag('new-feature'); console.log(value); ``` ## Next Steps The SDK is ready—now track user actions: * Send events in [Quickstart: Send Events](/quickstarts/events). * Explore targeting in [Targeting & Rollouts](/flags/targeting-and-rollouts). * See other options in [other SDKs](/sdks/overview) # CLI Source: https://docs.flagsync.com/sdks-cli/cli Use FlagSync’s CLI to generate TypeScript type definitions. ## Overview The `@flagsync/cli` generates TypeScript type definitions based on your flag configurations. Latest version available on npm Explore the source code on GitHub ## Installation Install the CLI with your preferred package manager: ```bash npm theme={null} npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add -D @flagsync/cli ``` ## Quickstart 1. **Authenticate with your FlagSync account:** ```bash terminal theme={null} npx flagsync login ``` 2. **Generate type definitions:** ```bash terminal theme={null} $ npx flagsync generate ✓ Select your SDK: React i Found 4 flags ✓ Generated flag types, saved to "gen/flags.d.ts" ``` 3. **Use in your code:** ```typescript app.jsx theme={null} import React from 'react'; import { useFlag } from '@flagsync/react-sdk'; function MyComponent() { // TypeScript knows this returns a boolean const { value: isEnabled } = useFlag('show-new-feature'); // TypeScript knows this returns "light" | "dark" | "auto" const { value: theme } = useFlag('theme-preference'); return (
{isEnabled && }
); } ``` The generated types will be saved to `gen/flags.d.ts`. Most default `tsconfig.json` setups include this file via a broad pattern like `**/*.ts`, but if you're using a custom config, make sure it's covered by the include array: `"include": ["**/*.ts"]` ## Generated Types The CLI generates TypeScript types based on your flag configurations. ```typescript Boolean Flags theme={null} // For boolean flags declare module "@flagsync/node-sdk" { export interface FeatureFlags { "enable-dark-mode": boolean; "show-beta-features": boolean; } } ``` ```typescript String Flags theme={null} // For string flags with variants declare module "@flagsync/react-sdk" { export interface FeatureFlags { "theme-color": "blue" | "red" | "green"; "welcome-message": "hello" | "welcome" | "hi there"; } } ``` ```typescript Number Flags theme={null} // For number flags with variants declare module "@flagsync/nestjs-sdk" { export interface FeatureFlags { "max-items": 10 | 25 | 50 | 100; "timeout-duration": 1000 | 5000 | 10000; } } ``` ```typescript JSON Flags theme={null} // For JSON/object flags declare module "@flagsync/nextjs-sdk" { export interface FeatureFlags { "config-object": object; "feature-settings": object; } } ``` ## Integration Examples A few integration examples for FlagSync's SDKS. Supported SDKs: * [`@flagsync/react-sdk`](/sdks-client-side/react) * [`@flagsync/js-sdk`](/sdks-client-side/javascript) * [`@flagsync/node-sdk`](/sdks-server-side/nodejs) * [`@flagsync/nextjs-sdk`](/sdks-server-side/nextjs) * [`@flagsync/nestjs-sdk`](/sdks-server-side/nestjs) ### `@flagsync/react-sdk` ```typescript theme={null} import React from 'react'; import { useFlag } from '@flagsync/react-sdk'; function MyComponent() { // TypeScript knows this returns a boolean const { value: isEnabled } = useFlag('show-new-feature'); // TypeScript knows this returns "light" | "dark" | "auto" const { value: theme } = useFlag('theme-preference'); return (
{isEnabled && }
); } ``` ### `@flagsync/nextjs-sdk` ```jsx page.tsx theme={null} import { welcomeMessage } from '@/lib/flagsync'; export default function HomePage() { // TypeScript knows this returns "hello" | "welcome" | "hi there" const message = await welcomeMessage(); return

{message}; } ``` ```typescript @/lib/flagsync theme={null} import { flag } from 'flags/next'; import { getFlag } from '@/lib/flagsync/flag'; // TypeScript knows this returns "hello" | "welcome" | "hi there" export const welcomeMessage = flag({ key: 'welcome-message', async decide(params) { return getFlag(this.key, params); }, }); ``` ### `@flagsync/js-sdk` ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; // Initialize the SDK const factory = FlagSyncFactory({...}); const client = factory.client() await client.waitForReady(); // TypeScript knows this returns 10 | 25 | 50 | 100 const maxItems = client.flag('max-items'); ``` ## Commands ### `flagsync login` Authenticates the CLI with your FlagSync account using a secure OAuth2 flow. ```bash theme={null} npx flagsync login ``` Opens your browser for authentication, then walks you through selecting your project context **Prompts:** * **Organization**: Choose which FlagSync organization to use * **Workspace**: Select the workspace containing your flags ### `flagsync logout` Disconnects the CLI from your FlagSync account. ```bash theme={null} npx flagsync logout ``` Clears your saved login credentials. You'll need to run `flagsync login` again to use other commands. ### `flagsync generate` Creates TypeScript definitions for your feature flags. ```bash theme={null} npx flagsync generate ``` Pulls your flag definitions and generates type-safe TypeScript code in `gen/flags.d.ts`. **Prompts:** * **SDK Selection**: Choose your framework: * [`@flagsync/react-sdk`](/sdks-client-side/react) * [`@flagsync/js-sdk`](/sdks-client-side/javascript) * [`@flagsync/node-sdk`](/sdks-server-side/nodejs) * [`@flagsync/nextjs-sdk`](/sdks-server-side/nextjs) * [`@flagsync/nestjs-sdk`](/sdks-server-side/nestjs) ## File Structure After running `flagsync generate`, your project will have: ``` your-project/ ├── gen/ │ └── flags.d.ts # Generated type definitions ├── package.json └── ... your other files ``` The generated `flags.d.ts` file contains: * Module declaration for your chosen SDK * `FeatureFlags` interface with all your flags * Type-safe flag key constants The generated types will be saved to `gen/flags.d.ts`. Most default `tsconfig.json` setups include this file via a broad pattern like `**/*.ts`, but if you're using a custom config, make sure it's covered by the include array: `"include": ["**/*.ts"]` # Overview Source: https://docs.flagsync.com/sdks-cli/overview Learn about FlagSync’s CLI for generating TypeScript type definitions. ## Overview The `@flagsync/cli` bridges the gap between your feature flags in the FlagSync dashboard and your code. It automatically generates TypeScript type definitions based on your flag configurations, providing: * **Type Safety**: Compile-time checking for flag keys and values * **Auto-completion**: IntelliSense support for flag names and values * **Secure Authentication**: OAuth2 PKCE flow for safe credential management typescript icon Generate TypeScript type definitions for your feature flags. ### Supported SDKs * [`@flagsync/react-sdk`](/sdks-client-side/react) * [`@flagsync/js-sdk`](/sdks-client-side/javascript) * [`@flagsync/node-sdk`](/sdks-server-side/nodejs) * [`@flagsync/nextjs-sdk`](/sdks-server-side/nextjs) * [`@flagsync/nestjs-sdk`](/sdks-server-side/nestjs) ## Next Steps Get started with client-side SDKs: * Integrate with the [CLI](/sdks-cli/cli). * Set up an SDK in [SDK Setup](/sdks/setup). * Check out the [Quickstart: SDK](/quickstarts/sdk) guide. # JavaScript SDK Source: https://docs.flagsync.com/sdks-client-side/javascript Integrate FlagSync feature flags into web applications. ## Overview The `@flagsync/js-sdk` integrates into web applications for client-side feature management and event tracking—ideal for single-user contexts like browser environments. Latest version available on npm Explore the source code on GitHub ## Installation Install the SDK with your preferred package manager: ```bash npm theme={null} npm install @flagsync/js-sdk npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add @flagsync/js-sdk yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add @flagsync/js-sdk pnpm add -D @flagsync/cli ``` ## Quickstart A basic example of using the SDK in a JavaScript application: ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; // Initialize the SDK const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123', // Unique identifier attributes: { plan: 'premium', country: 'US' } } }); // Get the client const client = factory.client() // Wait for SDK to be ready await client.waitForReady(); // Evaluate a flag const isFeatureEnabled = client.flag('my-first-kill-switch'); ``` ## Initialization ### Get Your SDK Key Find your client-side SDK key in your [workspace settings](https://www.flagsync.com/dashboard/settings/organization/workspaces/)—safe for web/mobile apps (keep server-side keys private). ### Initialize the SDK Initialize the SDK with your SDK key and a user context (e.g., user ID): ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user123', // Unique identifier attributes: { email: 'user@example.com' } } }); const client = factory.client(); ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Wait for Readiness Use events or promises to ensure the SDK is ready before evaluating flags. Always wait for SDK initialization before evaluating any flags. Initialization usually completes within 15–30ms, depending on flag count and ruleset complexity. ```typescript async/await theme={null} await client.waitForReady(); // SDK is ready ``` ```typescript async/await (throws) theme={null} // Throw an error if the SDK fails to initialize. try { await client.waitForReadyCanThrow(); // SDK is ready } catch (error) { // Handle initialization error } ``` ```typescript SDK_READY theme={null} import { FsEvent } from '@flagsync/js-sdk'; client.once(FsEvent.SDK_READY, () => { // SDK is ready }); ``` ```typescript SDK_READY_FROM_STORE theme={null} import { FsEvent } from '@flagsync/js-sdk'; client.once(FsEvent.SDK_READY_FROM_STORE, () => { // Emitted once the SDK initializes from LocalStorage // Fires quickly—no network request required // Data may be stale, not a replacement for SDK_READY }); ``` This event only fires when using the `localstorage` storage type; the default is `memory`. #### SDK Not Ready If the SDK isn’t ready, it returns the `defaultValue` or `control`: ```typescript theme={null} // SDK not ready client.flag('flag-one', false); // false (defaultValue) client.flag('flag-two'); // "control" ``` #### SDK Ready Once ready, `flag()` returns the server-evaluated value: ```typescript theme={null} await client.waitForReady(); const value = client.flag('flag-one'); // Server-evaluated value ``` * Client-side SDKs can bootstrap via `LocalStorage` or an initial flag set—values apply until the SDK is ready. * See [Flag Evaluation: Overview](/sdks-flag-evaluation/overview). ## Usage ### Evaluate Flags Evaluates a feature flag for the user context. Applies targeting rules, rollouts, and defaults values. ```typescript theme={null} client.flag(flagKey: string, defaultValue?: T): T; ``` #### FlagSync CLI When using the CLI, flag values are automatically inferred from the generated types: ```typescript theme={null} client.flag('layout'); // Type: 'v1' | 'v2' | 'v3' client.flag('killswitch'); // Type: boolean client.flag('price-discount'); // Type: 0.1 | 0.2 client.flag('price-discount', 0.5); // ❌ TS Error: Invalid default value client.flag('invalid-flag'); // ❌ TS Error: Invalid flag key ``` Without generated types, you **must** manually specify the type: ```typescript theme={null} client.flag<'v1' | 'v2'>('layout'); // Type: 'v1' | 'v2' client.flag('price-discount'); // Type: number client.flag('enable-feature', false); // Type: boolean (defaultValue must be true or false) client.flag('no-type') // Type: unknown ``` An [Impression](/impressions/generating) is automatically registered when `flag()` is called. ### Track Events Submit user actions with `track()`—use `eventValue` for numeric data or `properties` for rich context: ```typescript theme={null} client.track( eventKey: string, eventValue?: number | null, properties?: Record | null ); ``` There are two types of events: Captures measurable data like time or counts. Captures rich context like purchase details. ```typescript Numeric theme={null} client.track('page-load-time', 1.42); ``` ```typescript Property theme={null} client.track('purchase-event', null, { productId: '0x123', price: 49.99, discount: 0.20 }); ``` Create metrics like "Average Purchase Price" from events—see [Metrics Overview](/metrics/overview). ### SDK Event Listeners The SDK emits these events for SDK lifecycle management: * `SDK_UPDATE`: Emitted when flags are updated * `SDK_READY`: Emitted when the SDK is ready * `SDK_READY_FROM_STORE`: Emitted when flags are loaded from storage * `ERROR`: Emitted when an error occurs during initialization ```typescript theme={null} import { FsEvent } from '@flagsync/js-sdk'; // Flag updates client.on(FsEvent.SDK_UPDATE, () => { console.log(`Flags updated at ${new Date().toISOString()}`) }); ``` `SDK_UPDATE` does not fire if syncing is disabled. ## Error Handling ```typescript theme={null} import { FsServiceError } from '@flagsync/js-sdk'; // Via events client.on(FsEvent.ERROR, (error: FsServiceError) => { console.error('SDK Error:', error); }); // Via promises try { await client.waitForReadyCanThrow(); } catch (error) { console.error('Initialization Error:', error as FsServiceError); } ``` All exposed errors are normalized to `FsServiceError`. ## Configuration Configure the SDK with the `FsConfig` interface: ```typescript theme={null} interface FsConfig { sdkKey: string; // Required: Your SDK key core: { key: string; // Required: User identifier attributes?: Record; // Optional: Custom user attributes }; bootstrap?: Record; // Optional: Initial flag values storage?: { type?: 'memory' | 'localstorage'; // Optional: Storage type prefix?: string; // Optional: Storage key prefix }; sync?: { type?: 'ws' | 'sse' | 'poll' | 'off'; // Optional: Sync strategy (default: 'ws') pollRateInSec?: number; // Optional: Polling interval in seconds }; tracking?: { impressions?: { maxQueueSize: number; // Required: Max impressions queue size pushRateInSec: number; // Required: Impressions push rate (seconds) }; events?: { maxQueueSize: number; // Required: Max events queue size pushRateInSec: number; // Required: Events push rate (seconds) }; }; urls?: { ws?: string; // Optional: WebSocket sync URL sse?: string; // Optional: SSE sync URL flags?: string; // Optional: Flag fetch URL events?: string; // Optional: Events & impressions URL }; logger?: Partial; // Optional: Custom logger logLevel?: LogLevel; // Optional: Logging level metadata?: Record; // Optional: Additional metadata } ``` ### Custom Attributes Define user attributes for targeting in [Flags: User Segments](/flags/targeting-and-rollouts#user-segments). ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123', attributes: { plan: 'premium', country: 'US', userType: 'enterprise' } } }); ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Flag Syncing Configure flag update strategies with the `sync` object: `ws`, `sse`, `poll`, or `off`. By default, flag updates propagate in milliseconds over a WebSocket connection, ensuring the latest values are used in evaluations. Stream updates over a WebSocket connection—flag updates are reevaluated on the server and pushed to the client in real time: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'ws' // Default } }); ``` Stream updates via server-sent events (SSE): ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'sse' } }); ``` Poll the server on an interval: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'poll', pollRateInSec: 60 } }); ``` Disable syncing: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'off' } }); ``` ### Bootstrapping Initialize the SDK with a set of bootstrap flags: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, bootstrap: { 'my-first-kill-switch': false, 'another-flag': 'value' } }); ``` Bootstrapped values apply before the SDK is ready—see [Flag Evaluation: Overview](/sdks-flag-evaluation/overview). ### Storage Choose between memory and LocalStorage storage types: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, storage: { type: 'memory' } }); ``` ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user-123' }, storage: { type: 'localstorage' prefix: 'flagsync' // Optional: Custom prefix for storage keys } }); ``` The `SDK_READY_FROM_STORE` event fires when loading from LocalStorage—no network request needed, but data may be stale. ## Best Practices * Wait for SDK readiness before evaluating flags. * Select a sync strategy (`ws`/`sse`/`poll`/`off`) based on your application’s needs. * Add user attributes for targeted feature rollouts. * Consider bootstrapping for faster initial renders. ## Environment Variables Set the following environment variable: * `FLAGSYNC_SDK_KEY`: Your client-side FlagSync SDK key (required) # Overview Source: https://docs.flagsync.com/sdks-client-side/overview Learn about FlagSync’s client-side SDKs for web and mobile apps. ## Overview FlagSync’s client-side SDKs are designed for single-user contexts like web and mobile apps: User segment targeting rule creation For browser-based apps (e.g., SPAs, vanilla JS). User segment targeting rule creation For React-based web applications. Need another language or framework? Contact FlagSync Support to explore adding it to our roadmap. ## Avoid Flickering During SDK Initialization When using feature flags in web applications, rendering a page with default flag values before the SDK initializes can cause a "flicker" as content updates. To prevent this, consider these strategies: * **Initialize Early**: Prioritize the SDK initialize to evaluate flags sooner, minimizing delays. * **Delay Rendering**: Hide the page (e.g., set body to `display: none`, or use the `waitForReady` prop in the React SDK) until the SDK signals readiness, then show the correct content. SDK initialization time, usually 30-50 milliseconds, depends on flag count and ruleset complexity. * **Bootstrap Flags**: Provide initial flag values for immediate use, avoiding fetch delays. See [Bootstrapping](/sdks-client-side/javascript#bootstrapping) for details on providing initial flag values. ## Next Steps Get started with client-side SDKs: * Learn about server-side SDKs in [Server-Side SDKs](/sdks-server-side/overview). * Set up an SDK in [Setup](/sdks/setup). * Start with [Quickstart: SDK](/quickstarts/sdk). # React SDK Source: https://docs.flagsync.com/sdks-client-side/react Integrate FlagSync feature flags into React applications using hooks and providers. ## Overview The `@flagsync/react-sdk` integrates into React applications for client-side feature management and event tracking—ideal for single-user contexts like browser environments. > Requires React 16.3+ due to its dependency on the React Context API. Latest version available on npm Explore the source code on GitHub ## Installation Install the SDK with your preferred package manager: ```bash npm theme={null} npm install @flagsync/react-sdk npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add @flagsync/react-sdk yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add @flagsync/react-sdk pnpm add -D @flagsync/cli ``` ## Quickstart A basic example of using the SDK in a React application: ```jsx theme={null} import { useFlag, FlagSyncProvider } from '@flagsync/react-sdk'; function MyApp() { return ( ); } function MyComponent() { const { value, isReady, isReadyFromStore } = useFlag('my-first-kill-switch', false); if (!isReady) { return
Loading...
; } return
Feature is {value ? 'enabled' : 'disabled'}
; } ``` ## Initialization ### Get Your SDK Key Find your client-side SDK key in your [workspace settings](https://www.flagsync.com/dashboard/settings/organization/workspaces/)—safe for web/mobile apps (keep server-side keys private). ### Initialize the SDK Wrap your application with `FlagSyncProvider` and provide the required configuration: ```tsx theme={null} import { FlagSyncProvider } from '@flagsync/react-sdk'; function App() { return ( {/* Your app components */} ); } ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Wait for Readiness Prevent flickering by ensuring the SDK is ready before your app renders. Use the `waitForReady` prop in `FlagSyncProvider` to delay rendering until the SDK is initialized, or check readiness manually with hooks or render prop components: Add `waitForReady` to `FlagSyncProvider` to delay rendering until the SDK is ready, avoiding flicker during initialization. ```tsx theme={null} ``` Check isReady with hooks like `useFlag`, `useFlags`, or `useFlagSyncClient` to control rendering ```typescript useFlag theme={null} const { isReady, isReadyFromStore } = useFlag('my-first-kill-switch', false); ``` ```typescript useFlags theme={null} const { isReady, isReadyFromStore } = useFlags() ``` ```typescript useFlagSyncClient theme={null} const { isReady, isReadyFromStore } = useFlagSyncClient(); ``` Identical properties are provided in ``, and ``. #### SDK Not Ready If the SDK isn’t ready, it returns the `defaultValue` or `control`: ```typescript theme={null} // value: false (defaultValue) isReady: false const { value, isReady } = useFlag('flag-one', false); // value: "control", isReady: false const { value, isReady } = useFlag('flag-two'); ``` #### SDK Ready Once ready, hooks return the server-evaluated value: ```typescript theme={null} // value: Server-evaluated value, isReady: true const { value, isReady } = useFlag('flag-one'); ``` * Client-side SDKs can bootstrap via `LocalStorage` or an initial flag set—values apply until the SDK is ready. * See [Flag Evaluation: Overview](/sdks-flag-evaluation/overview). ## Usage ### Evaluate Flags Evaluates a feature flag for user context. Applies targeting rules, rollouts, and defaults values. ```typescript useFlag theme={null} // Get a single flag value const { value } = useFlag('my-first-kill-switch', defaultValue); ``` ```typescript useFlags theme={null} // Get multiple flag values const { flags } = useFlags({ 'flag-1': false, 'flag-2': 'dark-mode' }); ``` #### FlagSync CLI When using the CLI, flag values are automatically inferred from the generated types: ```typescript theme={null} useFlag('layout'); // Type: 'v1' | 'v2' | 'v3' useFlag('killswitch'); // Type: boolean useFlag('price-discount'); // Type: 0.1 | 0.2 useFlag('price-discount', 0.5); // ❌ TS Error: Invalid default value useFlag('invalid-flag'); // ❌ TS Error: Invalid flag key ``` Without generated types, you **must** manually specify the type: ```typescript theme={null} useFlag<'v1' | 'v2'>('layout'); // Type: 'v1' | 'v2' useFlag('price-discount'); // Type: number useFlag('enable-feature', false); // Type: boolean (defaultValue must be true or false) useFlag('no-type') // Type: unknown ``` An [Impression](/impressions/generating) is automatically logged either of the flag hooks are called. ### Track Events Submit user actions with the `useTrack` hook, which supports two usage patterns: Bind the hook to a specific event key for repeated tracking: ```tsx theme={null} const track = useTrack('page-visit'); // Bound to eventKey useEffect(() => track()) ``` Use a generic track function to specify the event key at call time: ```tsx theme={null} const track = useTrack(); ``` * See [JavaScript SDK: Track Events](/sdks-client-side/javascript#track-events) for more on `track()`. * See [Events: Tracking](/events/tracking) to learn about numeric and property events. ### SDK Event Listeners The SDK emits these events for SDK lifecycle management: * `SDK_UPDATE`: Emitted when flags are updated * `SDK_READY`: Emitted when the SDK is ready * `SDK_READY_FROM_STORE`: Emitted when flags are loaded from storage * `ERROR`: Emitted when an error occurs during initialization Access these events using the `useFlagSyncClient` hook: ```tsx theme={null} import {useFlagSyncClient} from '@flagsync/react-sdk' const client = useFlagSyncClient(); useEffect(() => { const onUpdate = () => { console.log('Flags updated:', client.lastUpdated); }; client.on('SDK_UPDATE', onUpdate); return () => client.off('SDK_UPDATE', onUpdate); }, [client]); ``` `SDK_UPDATE` does not fire if syncing is disabled. ## Configuration Configure the SDK with the `FsConfig` interface: ```typescript theme={null} interface FsConfig { sdkKey: string; // Required: Your SDK key core: { key: string; // Required: User identifier attributes?: Record; // Optional: Custom user attributes }; bootstrap?: Record; // Optional: Initial flag values storage?: { type?: 'memory' | 'localstorage'; // Optional: Storage type prefix?: string; // Optional: Storage key prefix }; sync?: { type?: 'ws' | 'sse' | 'poll' | 'off'; // Optional: Sync strategy (default: 'ws') pollRateInSec?: number; // Optional: Polling interval in seconds }; tracking?: { impressions?: { maxQueueSize: number; // Required: Max impressions queue size pushRateInSec: number; // Required: Impressions push rate (seconds) }; events?: { maxQueueSize: number; // Required: Max events queue size pushRateInSec: number; // Required: Events push rate (seconds) }; }; urls?: { ws?: string; // Optional: WebSocket sync URL sse?: string; // Optional: SSE sync URL flags?: string; // Optional: Flag fetch URL events?: string; // Optional: Events & impressions URL }; logger?: Partial; // Optional: Custom logger logLevel?: LogLevel; // Optional: Logging level metadata?: Record; // Optional: Additional metadata } ``` ### Custom Attributes Define user attributes for targeting in [Flags: User Segments](/flags/targeting-and-rollouts#user-segments). ```tsx theme={null} {/* Your app */} ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Flag Syncing Configure flag update strategies with the `sync` object: `ws`, `sse`, `poll`, or `off`. By default, flag updates propagate in milliseconds over a WebSocket connection, ensuring the latest values are used in evaluations. * Components using flag hooks re-render automatically—no event listeners needed. * To disable this behavior, set `sync` to `off`, requiring a page refresh to fetch updated flags. Stream updates over a WebSocket connection—flag updates are reevaluated on the server and pushed to the client in real time: ```typescript theme={null} const config: FsConfig = { sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'ws' // Default } }; ``` Stream updates via server-sent events (SSE): ```typescript theme={null} const config: FsConfig = { sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'sse' } }; ``` Poll the server on an interval: ```typescript theme={null} const config: FsConfig = { sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'poll', pollRateInSec: 60 } }; ``` Disable syncing: ```typescript theme={null} const config: FsConfig = { sdkKey: 'your-sdk-key', core: { key: 'user-123' }, sync: { type: 'off' } }; ``` ### Bootstrapping Initialize the SDK with a set of bootstrap flags: ```tsx theme={null} {/* Your app */} ``` Bootstrapped values apply before the SDK is ready—see [Flag Evaluation: Overview](/sdks-flag-evaluation/overview). ### Storage Choose between memory and LocalStorage storage types: ```typescript theme={null} const config: FsConfig = { sdkKey: 'your-sdk-key', core: { key: 'user-123' }, storage: { type: 'memory' } }; ``` ```typescript theme={null} const config: FsConfig = { sdkKey: 'your-sdk-key', core: { key: 'user-123' }, storage: { type: 'localstorage' prefix: 'flagsync' // Optional: Custom prefix for storage keys } }; ``` Use the `useFlagSyncClient` to get the `client.isReadyFromStore` property. ## Best Practices * Use `isReady` checks to handle loading states. See [Wait for Readiness](#wait-for-readiness). * Select a sync strategy (`ws`/`sse`/`poll`/`off`) based on your application’s needs. * Use `useTrack` for consistent event tracking in components. * Add user attributes for targeted feature rollouts. * Consider bootstrapping for faster initial renders. ## Environment Variables Set the following environment variable: * `FLAGSYNC_SDK_KEY`: Your client-side FlagSync SDK key (required) # Overview Source: https://docs.flagsync.com/sdks-flag-evaluation/overview Understand how FlagSync evaluates flags for users. ## Flag Evaluation Flow FlagSync evaluates flags using the same logic flow across SDKs: If not, the SDK returns the `defaultValue` (e.g., `false`) or `control` string. ```typescript theme={null} // Before SDK is ready const one = client.flag('flag-one', false); // false (defaultValue) const two = client.flag('flag-two'); // "control" await client.waitForReady(); ``` Client-side SDKs can bootstrap via `LocalStorage` or from an initial flag set, using those values until the SDK initializes with server data. If the flag key isn’t found, the SDK returns the `defaultValue` or `control`. ```typescript theme={null} // Unknown flag, returns true (defaultValue) const value = client.flag('foobarbaz', true); ``` If the flag key was included in the bootstrapped values, this value will be returned. * If **disabled**: The default "off" variant is returned, halting further evaluation. * If **enabled**: The algorithm proceeds to targeting and rollout checks. Explore [Flags: All Users](/flags/targeting-and-rollouts#all-users) to learn about default variants. * See [Targeting](/sdks-flag-evaluation/targeting) for evaluation logic. * See [Flags: User Segments](/flags/targeting-and-rollouts#user-segments) to learn about targeting rules. * See [Rollouts](/sdks-flag-evaluation/rollouts) for evaluation logic. * See [Flags: Percentage Rollouts](/flags/targeting-and-rollouts#percentage-rollouts) to learn about rollouts. Returns the "on" variant if no rules or percentages apply. See [Flags: All Users](/flags/targeting-and-rollouts#all-users) to learn about default variants. ### Flow Diagram ```mermaid theme={null} graph TD A[Start] --> B{SDK Ready?} B -->|No| C[Return defaultValue/control] B -->|Yes| D{Flag Exists?} D -->|No| C D -->|Yes| F{Flag Enabled?} F -->|No| G[Return 'off' variant] F -->|Yes| H{Targeting Rules?} H -->|Yes| I{Evaluate Rules} H -->|No| J{Percentage Rollout?} I -->|Match Found| M[Return rule variant] I -->|No Match| J J -->|Yes| K[Return rollout variant] J -->|No| L[Return 'on' variant] C & G & M & L & K --> O[End] ``` ## Next Steps Dive deeper into the flag evaluation process: * Learn targeting logic in [Targeting](/sdks-flag-evaluation/targeting). * Explore rollout evaluation in [Rollouts](/sdks-flag-evaluation/rollouts). * Start with [Quickstart: SDK](/quickstarts/sdk) # Rollouts Source: https://docs.flagsync.com/sdks-flag-evaluation/rollouts Understand how FlagSync evaluates percentage rollouts for flags. ## Percentage Rollouts FlagSync uses a deterministic hashing algorithm to evaluate percentage rollouts, ensuring users receive the same variant on each evaluation. Set percentage distributions in the dashboard (e.g., 25% "Enabled", 75% "Disabled"). Percentage rollout distribution Hash the user context key (e.g., user ID, email, attributes) and flag seed (unique per flag and environment). ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user123' } }); ``` Normalize the hash to 0-99, placing users in buckets. e.g., a normalized value of 16 falls in the 0-24 bucket, serving "Enabled" at 25%. In the dashboard, you can reshuffle an active percentage rollout, changing the flag seed and reassigning users to new buckets. If no rollout applies, the default "on" variant is served. Return to [Flag Evaluation: Overview](/sdks-flag-evaluation/overview) for the full flow. ## Next Steps Explore more about flag evaluation and SDKs: * Learn targeting logic in [Targeting](/sdks-flag-evaluation/targeting). * Set up an SDK in [Setup](/sdks/setup). * Start with [Quickstart: SDK](/quickstarts/sdk). # Targeting Source: https://docs.flagsync.com/sdks-flag-evaluation/targeting Learn how FlagSync applies targeting rules during flag evaluation. ## User Segment Targeting Flags can have targeting rules to serve specific variants to user groups based on attributes: Set rules in the dashboard using attributes (e.g., `jobTitle = "QA Tester"`). User segment targeting rule creation Learn more about targeting in [Flags: User Segments](/flags/targeting-and-rollouts#user-segments). Within a rule, clauses use logical OR—e.g., serve "Enabled" to users with `jobTitle` of "QA Tester" or "PM". ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/js-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', core: { key: 'user123', attributes: { jobTitle: 'QA Testers' } } }); ``` If a flag has multiple rules, the first matching rule determines the variant served. A matched rule stops further evaluation; otherwise, it proceeds to [Rollouts](/sdks-flag-evaluation/rollouts). ## Next Steps Continue exploring flag evaluation: * Learn rollout logic in [Rollouts](/sdks-flag-evaluation/rollouts). * Set up an SDK in [Setup](/sdks/setup). * Start with [Quickstart: SDK](/quickstarts/sdk). # Nest.js SDK Source: https://docs.flagsync.com/sdks-server-side/nestjs Integrate FlagSync feature flags into Nest.js applications. ## Overview The `@flagsync/nest-sdk` integrates into [Nest.js](https://nestjs.com/) applications for server-side feature management and event tracking—ideal for backend services and APIs. Latest version available on npm Explore the source code on GitHub ## Installation Install the SDK with your preferred package manager: ```bash npm theme={null} npm install @flagsync/nestjs-sdk npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add @flagsync/nestjs-sdk yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add @flagsync/nestjs-sdk pnpm add -D @flagsync/cli ``` ## Quickstart A basic example of using the SDK in a Nest.js application—set up the SDK in two steps: Import `FlagSyncModule` in your `app.module.ts`: ```typescript app.module.ts theme={null} import { Module } from '@nestjs/common'; import { FlagSyncModule } from '@flagsync/nestjs-sdk'; @Module({ imports: [ FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', // other configuration options }), ], }) export class AppModule {} ``` Use `@InjectFlagSync()` to inject the client into a [Provider](https://docs.nestjs.com/providers) (e.g., service, controller, etc.): ```typescript app.controller.ts theme={null} import { Controller, Get } from '@nestjs/common'; import { FsClient, InjectFlagSync } from '@flagsync/nestjs-sdk'; import { UserContext } from '@app/context.decorator'; @Controller() export class AppController { constructor(@InjectFlagSync() private client: FsClient) {} @Get() async getMyFlag(@UserContext() context) { return this.client.flag(context, 'my-first-kill-switch'); } } ``` ## Initialization The SDK leverages the `onModuleDestroy` lifecycle event to automatically destroy the `FsClient` on application shutdown, releasing connections to FlagSync’s servers. To ensure proper cleanup, call `enableShutdownHooks` during application startup. See the Nest.js documentation for [Application Shutdown](https://docs.nestjs.com/fundamentals/lifecycle-events#application-shutdown) ### Get Your SDK Key Find your server-side SDK key in your [workspace settings](https://www.flagsync.com/dashboard/settings/organization/workspaces/). Keep server-side keys private to protect flag rules. ### Initialize the SDK Initialize the SDK in your Nest.js application using one of these methods: #### Synchronous Configuration Configure the SDK synchronously with `forRoot`: ```typescript theme={null} import { Module } from '@nestjs/common'; import { FlagSyncModule } from '@flagsync/nestjs-sdk'; @Module({ imports: [ FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', }), ], ... }) export class AppModule {} ``` #### Asynchronous Configuration Configure the SDK asynchronously with `forRootAsync`, ideal for dynamic configuration with `ConfigService`: ```typescript theme={null} import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { FlagSyncModule } from '@flagsync/nestjs-sdk'; @Module({ imports: [ ConfigModule.forRoot({ cache: true, isGlobal: true, }), FlagSyncModule.forRootAsync({ inject: [ConfigService], useFactory: async (configService: ConfigService) => { return { sdkKey: configService.get('FLAGSYNC_SDK_KEY'), }; }, }), ], ... }) export class AppModule {} ``` ### Wait for Readiness The SDK initializes automatically during module setup—no need to manually wait for readiness with the injected `FsClient`. ## User Context Decorator Simplify user context access by creating a [custom decorator](https://docs.nestjs.com/custom-decorators#decorator-composition) that returns an `FsUserContext` object. Pass this object to `flag()` and `track()` functions. This decorator enables passing `@UserContext()` as a parameter in controller methods. Refer to the Nest.js documentation for [Authentication](https://docs.nestjs.com/security/authentication) to learn about `AuthGuards`, which can append `user` incoming requests. ```typescript @app/context.decorator.ts theme={null} import { createParamDecorator, ExecutionContext } from '@nestjs/common'; import { FsUserContext } from '@flagsync/nestjs-sdk'; export const UserContext = createParamDecorator( (_, ctx: ExecutionContext): FsUserContext => { const request = ctx.switchToHttp().getRequest(); // Populated via middleware or an AuthGuard // Or use request.cookies, etc. const user = request.user; return { key: user.userId, attributes: { jobTitle: user.role, region: request.headers['x-region'] ?? 'Unknown', }, }; }, ); ``` ```typescript app.controller.ts theme={null} import { Controller, Get } from '@nestjs/common'; import { FsClient, InjectFlagSync } from '@flagsync/nestjs-sdk'; import { UserContext } from '@app/context.decorator'; @Controller() export class AppController { constructor(@InjectFlagSync() private client: FsClient) {} @Get() async getMyFlag(@UserContext() context) { return this.client.flag(context, 'my-first-kill-switch'); } } ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ## Usage ### Evaluate Flags Evaluates a feature flag for a given user context. Applies targeting rules, rollouts, and defaults values. ```typescript theme={null} client.flag(ctx: FsUserContext, flagKey: string, defaultValue?: T): T ``` ```typescript app.service.ts {10} theme={null} import { Injectable } from '@nestjs/common'; import { InjectFlagSync, FsClient, FsUserContext } from '@flagsync/nestjs-sdk'; @Injectable() export class AppService { constructor(@InjectFlagSync() private readonly client: FsClient) {} // ctx passed from the controller async doWork(ctx: FsUserContext) { const isEnabled = this.client.flag(ctx, 'feature-enabled', false); if (isEnabled) { // Feature is enabled } } } ``` #### FlagSync CLI When using the CLI, flag values are automatically inferred from the generated types: ```typescript theme={null} client.flag(ctx, 'layout'); // Type: 'v1' | 'v2' | 'v3' client.flag(ctx, 'killswitch'); // Type: boolean client.flag(ctx, 'price-discount'); // Type: 0.1 | 0.2 client.flag(ctx, 'price-discount', 0.5); // ❌ TS Error: Invalid default value client.flag(ctx, 'invalid-flag'); // ❌ TS Error: Invalid flag key ``` Without generated types, you **must** manually specify the type: ```typescript theme={null} client.flag<'v1' | 'v2'>(ctx, 'layout'); // Type: 'v1' | 'v2' client.flag(ctx, 'price-discount'); // Type: number client.flag(ctx, 'enable-feature', false); // Type: boolean (defaultValue must be true or false) client.flag(ctx, 'no-type') // Type: unknown ``` An [Impression](/impressions/generating) is automatically registered when `flag()` is called. ### Track Events Submit user actions with the `track` function: See [Events: Tracking](/events/tracking) to learn about numeric and property events. ```typescript checkout.service.ts {14, 23} theme={null} import { Injectable } from '@nestjs/common'; import { InjectFlagSync, FsClient, FsUserContext } from '@flagsync/nestjs-sdk'; import { PurchaseRequest } from '@app/types'; @Injectable() export class CheckoutService { constructor( @InjectFlagSync() private readonly client: FsClient, ) {} async handlePurchase(request: PurchaseRequest, context: FsUserContext) { // Property event this.client.track(context, 'purchase-request', null, request); // Time the operation const t0 = Date.now(); const order = await this.makePurchase(request); const receipt = await this.sendOrder(order) const t1 = Date.now() // Numeric event this.client.track(context, 'purchase-duration', t1 - t0); } } ``` ### SDK Event Listeners The SDK emits these events for SDK lifecycle management: * `SDK_UPDATE`: Emitted when flags are updated * `SDK_READY`: Emitted when the SDK is ready * `ERROR`: Emitted when an error occurs during initialization ```typescript theme={null} import { FsEvent } from '@flagsync/js-sdk'; // Flag updates this.client.on(FsEvent.SDK_UPDATE, () => { this.logger.log(`Flags updated at ${new Date().toISOString()}`) }); ``` `SDK_UPDATE` does not fire if syncing is disabled. ## Configuration Configure the SDK with the `FsConfig` interface: ```typescript theme={null} export interface FsConfig { sdkKey: string; sync?: { type?: 'ws' | 'sse' | 'poll' | 'off'; // Optional: Sync strategy (default: 'ws') pollRateInSec?: number; // Optional: Polling interval in seconds }; tracking?: { impressions?: { maxQueueSize: number; // Required: Max impressions queue size pushRateInSec: number; // Required: Impressions push rate (seconds) }; events?: { maxQueueSize: number; // Required: Max events queue size pushRateInSec: number; // Required: Events push rate (seconds) }; }; urls?: { ws?: string; // Optional: WebSocket sync URL sse?: string; // Optional: SSE sync URL flags?: string; // Optional: Flag fetch URL events?: string; // Optional: Events & impressions URL }; logger?: Partial; // Optional: Custom logger logLevel?: LogLevel; // Optional: Logging level metadata?: Record; // Optional: Additional metadata } ``` ### Custom Attributes * Define user attributes for targeting in [Flags: User Segments](/flags/targeting-and-rollouts#user-segments). * See [User Context Decorator](#user-context-decorator) for the recommended approach to building the context. ```typescript theme={null} const context: FsUserContext = { key: 'user-123', attributes: { plan: 'premium', country: 'US', userType: 'enterprise' } } ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Flag Syncing Configure flag update strategies with the `sync` object: `ws`, `sse`, `poll`, or `off`. By default, flag updates propagate in milliseconds over a WebSocket connection, ensuring the latest values are used in evaluations. Stream updates over a WebSocket connection—flag updates are reevaluated on the server and pushed to the client in real time: ```typescript theme={null} FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', sync: { type: 'ws' // Default } }); ``` Stream updates via server-sent events (SSE): ```typescript theme={null} FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', sync: { type: 'sse' } }); ``` Poll the server on an interval: ```typescript theme={null} FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', sync: { type: 'poll', pollRateInSec: 60 } }); ``` Disable syncing: ```typescript theme={null} FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', sync: { type: 'off' } }); ``` ### Bootstrapping Initialize the SDK with a set of bootstrap flags: ```typescript theme={null} FlagSyncModule.forRoot({ sdkKey: 'your-sdk-key', bootstrap: { 'my-feature': true, 'other-feature': false, }, }); ``` ## Best Practices * Select a sync strategy (`ws`/`sse`/`poll`/`off`) based on your application’s needs. * Create a [User Context Decorator](#user-context-decorator) for simplified context management. * Add user attributes for targeted feature rollouts. ## Environment Variables Set the following environment variable: * `FLAGSYNC_SDK_KEY`: Your server-side FlagSync SDK key (required) # Next.js SDK Source: https://docs.flagsync.com/sdks-server-side/nextjs Integrate FlagSync feature flags into Next.js applications with Vercel Flags. ## Overview The `@flagsync/nextjs-sdk` integrates into Next.js applications with [Vercel Flags](https://flags-sdk.dev/) for feature management and event tracking—ideal for SSR and static site generation workflows. View the latest version on npm Explore the source code on GitHub ## Installation Install the SDK and required dependencies with your preferred package manager: ```bash npm theme={null} npm install @flagsync/nextjs-sdk flags npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add @flagsync/nextjs-sdk flags yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add @flagsync/nextjs-sdk flags pnpm add -D @flagsync/cli ``` ## Quickstart Integrate FlagSync with [Vercel Flags](https://flags-sdk.dev/) in your Next.js app in just a few steps: Create the `client` and export a boolean `adapter` helper: ```ts @/lib/flagsync theme={null} import { createAdapter, createClient } from '@flagsync/nextjs-sdk'; const client = createClient({ sdkKey: process.env.FLAGSYNC_SDK_KEY!, }); // Boolean adapter export const adapter = createAdapter(client)(); ``` Use the `flag()` function to define your feature flag, and connect it to the `adapter`. ```ts @/lib/flagsync/flags theme={null} import { flag } from 'flags/next'; import { adapter } from '@/lib/flagsync'; export const killswitchFlag = flag({ key: 'my-first-kill-switch', adapter, identify: () => ({ key: 'user-123' }), // See note below }); ``` See [User Context Identification](#user-context-identification) for the recommended approach to building the context. Call your feature flag like an async function in a Server Component to get the evaluated value. ```tsx app/page.tsx theme={null} import { myFlag } from '@/lib/flagsync/flags'; export default async function Page() { const value = await killswitchFlag(); return
{killswitchFlag.key} is {value}
; } ```
## Initialization ### Get Your SDK Key Find your server-side SDK key in your [workspace settings](https://www.flagsync.com/dashboard/settings/organization/workspaces/). Keep server-side keys private to protect flag rules. ### Initialize the SDK Initialize the FlagSync client singleton with your server-side SDK key: ```typescript lib/flagsync.ts theme={null} import { createClient } from '@flagsync/nextjs-sdk'; export const client = createClient({ sdkKey: process.env.FLAGSYNC_SDK_KEY!, }); ``` ### Wait for Readiness The SDK automatically initializes during the Next.js App Router lifecycle—no manual waiting is required for Server Components. ## User Context Identification Define the user context with a custom `identify` function that returns an `FsUserContext` object. Pass this function to Vercel’s `flag()` function. User contexts enable personalized flag evaluations via [Individual Targeting](/flags/targeting-and-rollouts#user-segments) and consistent experiences during [Percentage Rollouts](/flags/targeting-and-rollouts#percentage-rollouts). Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. Create `identify` with the `createIdentify` helper, linking flags to user contexts. ```typescript @/lib/flagsync {14} theme={null} import { createAdapter, createClient, createIdentify, } from '@flagsync/nextjs-sdk'; import { getFlagSyncUserContext } from '@/lib/flagsync/user-context'; const client = createClient({ sdkKey: process.env.FLAGSYNC_SDK_KEY!, }); export const adapter = createAdapter(client)(); export const identify = createIdentify(getFlagSyncUserContext); ``` Create a helper function to construct the user context from request cookies, headers, or your application’s auth system. Adjust the file below to meet your needs. ```ts @/lib/flagsync/user-context {10} theme={null} import type { ReadonlyHeaders, ReadonlyRequestCookies } from 'flags'; import type { NextRequest } from 'next/server'; type FlagParamsType = { cookies: ReadonlyRequestCookies | NextRequest['cookies'], headers: ReadonlyHeaders | NextRequest['headers'], }; // Return the user context (FsUserContext) export async function getFlagSyncUserContext( params: FlagParamsType ): FsUserContext { const userId = cookies.get('user-id')?.value; const visitorId = cookies.get('visitor-id')?.value; return { key: userId ?? visitorId, attributes: { region: params.headers.get('x-region'), userAgent: params.headers.get('user-agent') } }; }; ``` The `key` is set using a persistent `userId` or `visitorId` from cookies, falling back to a generated ID with `nanoid()`. For proper MAU tracking and consistent flag evaluations, ensure this `key` is unique and persistent across requests—see [User Context Best Practices](/sdks/overview#user-context-best-practices). Use middleware to set user identification cookies, simplifying context retrieval in `getFlagSyncUserContext`. ```typescript middleware.ts theme={null} import { jwtVerify } from 'jose'; import { NextRequest, NextResponse } from 'next/server'; import { nanoid } from 'nanoid'; const jwtSecret = new TextEncoder().encode('your-jwt-secret-key'); export async function middleware(request: NextRequest) { const response = NextResponse.next(); const jwt = request.cookies.get('jwt')?.value; // Replace this with your own logic to identify the user let user; if (jwt) { const { payload } = await jwtVerify(jwt, jwtSecret); user = payload; } if (user?.userId) { // Set the user-id cookie response.cookies.set('user-id', user.userId); } else { // Set the visitor-id cookie const visitorId = request.cookies.get('visitor-id')?.value response.cookies.set('visitor-id', visitorId ?? nanoid()); } return response; } ``` Pass `identify` to the flag definition. This connects flag evaluation to the user context. ```typescript @/lib/flagsync/flags {7} theme={null} import { flag } from 'flags/next'; import { adapter, identify } from '@/lib/flagsync'; export const killswitchFlag = flag({ key: 'my-first-kill-switch', adapter, identify, }); ``` ## Usage ### Evaluate Flags The are two distinct approaches for evaluating flags, each with different setup requirements and type-safety guarantees. * **With the FlagSync CLI (Recommended)**: This approach provides maximum type safety. It automatically generates types that validate your flag keys and infer their specific return values. * **Manual Typing**: If you aren't using the CLI, this method still provides strong type safety for a flag's return value, but requires you to create and manage type-specific adapters manually. #### FlagSync CLI When using the CLI, you must use the `createTypedFlag` function from the `@flagsync/nextjs-sdk` to build a type-safe flag function. This approach provides full type safety: from key validation to inferred return values, which isn't possible with the native `flags/next` package as it's unaware of your custom types. First, run the [FlagSync CLI](/sdks-cli/cli) to generate a `flags.d.ts` file, mapping your flag keys to their specific data types. ```typescript gen/flags.d.ts theme={null} // THIS FILE WAS GENERATED BY FLAGSYNC-CLI import { FeatureFlags } from "@flagsync/nextjs-sdk"; declare module "@flagsync/nextjs-sdk" { export interface FeatureFlags { "my-first-kill-switch": boolean; "price-discount": 0.1 | 0.2 | 0.3; } } ``` Create and export a `flag` function with the `createTypedFlag` factory. ```typescript @lib/flagsync {13} theme={null} import { createClient, createIdentify, createTypedFlag, } from '@flagsync/nextjs-sdk'; import { getFlagSyncUserContext } from '@/lib/flagsync/user-context'; const client = createClient({ sdkKey: process.env.FLAGSYNC_SDK_KEY! }); export const { flag } = createTypedFlag(client); export const identify = createIdentify(getFlagSyncUserContext); ``` Now you can define all your flags. Thanks to the generated types, you'll get full autocompletion for keys, and TypeScript will automatically infer the correct return type for each flag. ```typescript @lib/flagsync/flags {4,10} theme={null} import { flag, identify } from '@/lib/flagsync'; // The return value of killswitchFlag() is now Promise. export const killswitchFlag = flag({ identify, key: 'my-first-kill-switch', }); // The return value of discountFlag() is now Promise<0.1 | 0.2 | 0.3> export const discountFlag = flag({ identify, key: 'price-discount', }); ``` There's no need for an `adapter` when using the typed flag function. Await the flag definition in Server Components: ```jsx app/page.tsx theme={null} import { killswitchFlag } from '@/lib/flagsync/flags'; export default async function Page() { const value = await killswitchFlag(); // Promise return (
The value of {killswitchFlag.key} is {value}
); } ```
An [Impression](/impressions/generating) is automatically registered when you evaluate the flag. #### Manual Typing If you're not using the FlagSync CLI, you can still achieve type safety on your flag's return values. This approach requires you to manually specify each flag's expected type by creating and using type-specific adapters. You'll use the native `flag` function from `flags/next` and provide it with an adapter that has been pre-typed. Create an adapter for each data type you need. This ensures that the return value of your flag function is correctly typed. ```typescript @lib/flagsync {17-20} theme={null} import { createClient, createIdentify, createAdapter, // Renamed from createTypedFlag for clarity } from '@flagsync/nextjs-sdk'; import { getContext } from '@/lib/flagsync/user-context'; export const client = createClient({ sdkKey: process.env.FLAGSYNC_SDK_KEY!, }); // The factory creates adapters const adapterFactory = createAdapter(client); // Create an adapter for each data type you need export const boolAdapter = adapterFactory(); export const stringAdapter = adapterFactory(); export const numberAdapter = adapterFactory(); export const jsonAdapter = adapterFactory<{ foo: string }>(); export const identify = createIdentify(getContext); ``` When defining your flags, import the native `flag` function from `flags/next` and pass the corresponding typed adapter you created. This ensures the flag's return value and `defaultValue` are correctly typed. ```typescript @lib/flagsync/flags {13,22} theme={null} import { flag } from 'flags/next'; import { boolAdapter, numberAdapter, identify, } from '@/lib/flagsync'; // Use the boolAdapter for boolean flags. // The return value of killswitchFlag() is now Promise. export const killswitchFlag = flag({ identify, key: 'my-first-kill-switch', adapter: boolAdapter, defaultValue: false, // This must be a boolean }); // Use the numberAdapter for number-based flags. // The return value of discountFlag() is now Promise. export const discountFlag = flag({ identify, key: 'price-discount', adapter: numberAdapter, defaultValue: 0.1, // This must be a number }); ``` Await the flag definition in Server Components: ```jsx app/page.tsx theme={null} import { killswitchFlag } from '@/lib/flagsync/flags'; export default async function Page() { const value = await killswitchFlag(); // Promise return (
The value of {killswitchFlag.key} is {value}
); } ```
### Track Events Submit user actions with the `track` function: ```typescript api/checkout/route.js {18, 27} theme={null} import { cookies } from 'next/headers'; import { client, identify } from '@/lib/flagsync'; import { api } from '@/lib/api'; export async function POST(request) { const { product } = await request.json(); const cookieStore = cookies(); // ReadonlyRequestCookies const headerStore = headers(); // ReadonlyHeaders const context = await identify({ cookies: cookieStore, headers: headerStore }); // Property event client.track(context, 'purchase-event', null, product); // Time the operation const t0 = Date.now(); const order = await api.makePurchase(request); const receipt = await api.sendOrder(order) const t1 = Date.now() // Numeric event client.track(context, 'purchase-duration', t1 - t0); return Response.json({ success: true }); } ``` See [Events: Tracking](/events/tracking) to learn about numeric and property events. ### SDK Event Listeners The SDK emits these events for SDK lifecycle management: * `SDK_UPDATE`: Emitted when flags are updated * `SDK_READY`: Emitted when the SDK is ready * `ERROR`: Emitted when an error occurs during initialization ```typescript theme={null} import { FsEvent } from '@flagsync/js-sdk'; // Flag updates client.on(FsEvent.SDK_UPDATE, () => { console.log(`Flags updated at ${new Date().toISOString()}`) }); ``` `SDK_UPDATE` does not fire if syncing is disabled. ## Configuration Configure the SDK with the `FsConfig` interface: ```typescript theme={null} export interface FsConfig { sdkKey: string; sync?: { type?: 'ws' | 'sse' | 'poll' | 'off'; // Optional: Sync strategy (default: 'ws') pollRateInSec?: number; // Optional: Polling interval in seconds }; tracking?: { impressions?: { maxQueueSize: number; // Required: Max impressions queue size pushRateInSec: number; // Required: Impressions push rate (seconds) }; events?: { maxQueueSize: number; // Required: Max events queue size pushRateInSec: number; // Required: Events push rate (seconds) }; }; urls?: { ws?: string; // Optional: WebSocket sync URL sse?: string; // Optional: SSE sync URL flags?: string; // Optional: Flag fetch URL events?: string; // Optional: Events & impressions URL }; logger?: Partial; // Optional: Custom logger logLevel?: LogLevel; // Optional: Logging level metadata?: Record; // Optional: Additional metadata } ``` ### Custom Attributes * Define user attributes for targeting in [Flags: User Segments](/flags/targeting-and-rollouts#user-segments). * See [User Context Identification](#user-context-identification) for the recommended approach to building the context. ```typescript theme={null} const context: FsUserContext = { key: 'user-123', attributes: { plan: 'premium', country: 'US', userType: 'enterprise' } } ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Flag Syncing Configure flag update strategies with the `sync` object: `ws`, `sse`, `poll`, or `off`. By default, flag updates propagate in milliseconds over a WebSocket connection, ensuring the latest values are used in evaluations. Stream updates over a WebSocket connection—flag updates are reevaluated on the server and pushed to the client in real time: ```typescript theme={null} createClient({ sdkKey: 'your-sdk-key', sync: { type: 'ws' // Default } }); ``` Stream updates via server-sent events (SSE): ```typescript theme={null} createClient({ sdkKey: 'your-sdk-key', sync: { type: 'sse' } }); ``` Poll the server on an interval: ```typescript theme={null} createClient({ sdkKey: 'your-sdk-key', sync: { type: 'poll', pollRateInSec: 60 } }); ``` Disable syncing: ```typescript theme={null} createClient({ sdkKey: 'your-sdk-key', sync: { type: 'off' } }); ``` ### Bootstrapping Initialize the SDK with a set of bootstrap flags: ```typescript theme={null} createClient({ sdkKey: 'your-sdk-key', bootstrap: { 'my-feature': true, 'other-feature': false, }, }); ``` ## Best Practices * Select a sync strategy (`ws`/`sse`/`poll`/`off`) based on your application’s needs. * Follow [User Context Identification](#user-context-identification) for simplified context management. * Add user attributes for targeted feature rollouts. ## Environment Variables Set the following environment variable: * `FLAGSYNC_SDK_KEY`: Your server-side FlagSync SDK key (required) # Node.js SDK Source: https://docs.flagsync.com/sdks-server-side/nodejs Integrate FlagSync feature flags into Node.js applications. ## Overview The `@flagsync/node-sdk` integrates into Node.js applications for server-side feature management and event tracking—ideal for backend services and APIs. Latest version available on npm Explore the source code on GitHub ## Installation Install the SDK with your preferred package manager: ```bash npm theme={null} npm install @flagsync/node-sdk npm install -D @flagsync/cli ``` ```bash yarn theme={null} yarn add @flagsync/node-sdk yarn add -D @flagsync/cli ``` ```bash pnpm theme={null} pnpm add @flagsync/node-sdk pnpm add -D @flagsync/cli ``` ## Quickstart A basic example of using the SDK in a Node.js application (e.g., an Express server): ```typescript theme={null} import express, { Request, Response } from 'express'; import { FlagSyncFactory, FsUserContext } from '@flagsync/node-sdk'; import { getFlagSyncUserContext } from '@/lib/flagsync/user-context'; const app = express(); const port = 3000; // Initialize the SDK const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key'}); // Get the client const client = factory.client(); // Wait for SDK readiness await client.waitForReady(); app.get('/', async (req: Request, res: Response) => { const ctx = getFlagSyncUserContext(req); // Evaluate a flag with user context const isEnabled: boolean = client.flag(ctx, 'feature-enabled', false); if (isEnabled) { res.send('Feature is ON'); } else { res.send('Feature is OFF'); } }); app.listen(port, () => { console.log(`Server is running on http://localhost:${port}`); }); ``` See [User Context Identification](#user-context-identification) for details on the `getFlagSyncUserContext` object. ## Initialization ### Get Your SDK Key Find your server-side SDK key in your [workspace settings](https://www.flagsync.com/dashboard/settings/organization/workspaces/). Keep this key private and secure. ### Initialize the SDK Initialize the SDK with your SDK key: ```typescript theme={null} import { FlagSyncFactory } from '@flagsync/node-sdk'; const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key' }); const client = factory.client(); ``` ### Wait for Readiness Use promises or events to ensure the SDK is ready before evaluating flags. Always wait for SDK initialization before evaluating any flags. Initialization usually completes within 30–50ms, depending on flag count and ruleset complexity. ```typescript async/await theme={null} await client.waitForReady(); // SDK is ready ``` ```typescript async/await (throws) theme={null} // Throw an error if the SDK fails to initialize try { await client.waitForReadyCanThrow(); // SDK is ready } catch (error) { // Handle initialization error } ``` ```typescript theme={null} import { FsEvent } from '@flagsync/node-sdk'; client.once(FsEvent.SDK_READY, () => { // SDK is ready }); ``` #### SDK Not Ready If the SDK isn't ready, it returns the `defaultValue` or `control`: ```typescript theme={null} // SDK not ready client.flag(ctx, 'flag-one', false); // false (defaultValue) client.flag(ctx, 'flag-two'); // "control" ``` #### SDK Ready Once ready, `flag()` returns the server-evaluated value: ```typescript theme={null} await client.waitForReady(); const value = client.flag(ctx, 'flag-one'); // Server-evaluated value ``` ## User Context Identification Define the user context with a helper function that returns an `FsUserContext` object. Pass this object to `flag()` and `track()` functions. User contexts enable personalized flag evaluations via [Individual Targeting](/flags/targeting-and-rollouts#user-segments) and consistent experiences during [Percentage Rollouts](/flags/targeting-and-rollouts#percentage-rollouts). Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. Create a helper function to construct the user context from request cookies, headers, or your application's auth system. Adjust the file below to meet your needs. ```typescript lib/flagsync/user-context.ts theme={null} export function getFlagSyncUserContext(req): FsUserContext { const userId = req.cookies['user-id']; const visitorId = req.cookies['visitor-id']; return { key: userId ?? visitorId, attributes: { userAgent: req.headers['user-agent'], region: req.headers['x-region'], } }; } ``` The `key` is set using a persistent `userId` or `visitorId` from cookies, falling back to a generated ID with `nanoid()`. For proper MAU tracking and consistent flag evaluations, ensure this `key` is unique and persistent across requests—see [User Context Best Practices](/sdks/overview#user-context-best-practices). Use Express middleware to set user identification cookies, simplifying context retrieval in the helper function. Middleware is optional—user identification logic can be implemented directly in `getFlagSyncUserContext()` or elsewhere in your application. ```typescript lib/flagsync/identify.ts theme={null} import { nanoid } from 'nanoid'; import { verify } from 'jsonwebtoken'; export function identifyUser(req, res, next) { // Replace this with your own logic to identify the user const user = verify(req.cookies['jwt'], process.env.JWT_SECRET) if (user?.userId) { // Set the user-id cookie res.cookie('user-id', user.userId); } else { // Set the visitor-id cookie const visitorId = req.cookies['visitor-id'] ?? nanoid(); res.cookie('visitor-id', visitorId); } next(); } ``` In your Express routes, use the helper to build the `FsUserContext` for flag evaluations or event tracking. ```typescript app.ts {11-12} theme={null} import express from 'express'; import cookieParser from 'cookie-parser'; import { identifyUser } from '@/lib/flagsync/identify'; import { getFlagSyncUserContext } from '@/lib/flagsync/user-context'; const app = express(); app.use(cookieParser()); app.use(identifyUser); // Identify user middleware app.post('/feature', async (req, res) => { const ctx = getFlagSyncUserContext(req); const isEnabled = client.flag(ctx, 'feature-enabled', false); res.status(200).json({ enabled: isEnabled }); }); ``` ## Usage ### Evaluate Flags Evaluates a feature flag for a given user context. Applies targeting rules, rollouts, and defaults values. ```typescript theme={null} client.flag(ctx: FsUserContext, flagKey: string, defaultValue?: T): T ``` ```typescript app.ts {3} theme={null} app.post('/feature', async (req, res) => { const ctx = getFlagSyncUserContext(req); const isEnabled = client.flag(ctx, 'feature-enabled', false); res.status(200).json({ enabled: isEnabled }); }); ``` #### FlagSync CLI When using the CLI, flag values are automatically inferred from the generated types: ```typescript theme={null} client.flag(ctx, 'layout'); // Type: 'v1' | 'v2' | 'v3' client.flag(ctx, 'killswitch'); // Type: boolean client.flag(ctx, 'price-discount'); // Type: 0.1 | 0.2 client.flag(ctx, 'price-discount', 0.5); // ❌ TS Error: Invalid default value client.flag(ctx, 'invalid-flag'); // ❌ TS Error: Invalid flag key ``` Without generated types, you **must** manually specify the type: ```typescript theme={null} client.flag<'v1' | 'v2'>(ctx, 'layout'); // Type: 'v1' | 'v2' client.flag(ctx, 'price-discount'); // Type: number client.flag(ctx, 'enable-feature', false); // Type: boolean (defaultValue must be true or false) client.flag(ctx, 'no-type') // Type: unknown ``` An [Impression](/impressions/generating) is automatically registered when `flag()` is called. ### Track Events Submit user actions with the `track()` function: ```typescript app.ts {8, 15} theme={null} app.post('/checkout', async (req: Request, res: Response) => { const request: PurchaseRequest = req.body; const ctx: FsUserContext = { key: 'user-123', email: 'user@example.com', }; client.track(ctx, 'purchase-request', null, request); const t0 = Date.now(); const order = await makePurchase(request); const receipt = await sendOrder(order); const t1 = Date.now(); client.track(ctx, 'purchase-duration', t1 - t0); res.status(200).json({ success: true, receipt }); }); ``` ```typescript track() signature theme={null} track( context: FsUserContext, eventKey: string, eventValue?: number | null, properties?: Record | null ); ``` See [Events: Tracking](/events/tracking) to learn about numeric and property events. ### SDK Event Listeners The SDK emits these events for SDK lifecycle management: * `SDK_UPDATE`: Emitted when flags are updated * `SDK_READY`: Emitted when the SDK is ready * `ERROR`: Emitted when an error occurs during initialization ```typescript theme={null} import { FsEvent } from '@flagsync/node-sdk'; // Flag updates client.on(FsEvent.SDK_UPDATE, () => { console.log(`Flags updated at ${new Date().toISOString()}`); }); ``` `SDK_UPDATE` does not fire if syncing is disabled. ## Error Handling ```typescript theme={null} import { FsServiceError } from '@flagsync/node-sdk'; // Via events client.on(FsEvent.ERROR, (error: FsServiceError) => { console.error('SDK Error:', error); }); // Via promises try { await client.waitForReadyCanThrow(); } catch (error) { console.error('Initialization Error:', error as FsServiceError); } ``` All exposed errors are normalized to `FsServiceError`. ## Configuration Configure the SDK with the `FsConfig` interface: ```typescript theme={null} export interface FsConfig { sdkKey: string; sync?: { type?: 'ws' | 'sse' | 'poll' | 'off'; // Optional: Sync strategy (default: 'ws') pollRateInSec?: number; // Optional: Polling interval in seconds }; tracking?: { impressions?: { maxQueueSize: number; // Required: Max impressions queue size pushRateInSec: number; // Required: Impressions push rate (seconds) }; events?: { maxQueueSize: number; // Required: Max events queue size pushRateInSec: number; // Required: Events push rate (seconds) }; }; urls?: { ws?: string; // Optional: WebSocket sync URL sse?: string; // Optional: SSE sync URL flags?: string; // Optional: Flag fetch URL events?: string; // Optional: Events & impressions URL }; logger?: Partial; // Optional: Custom logger logLevel?: LogLevel; // Optional: Logging level metadata?: Record; // Optional: Additional metadata } ``` ### Custom Attributes * Define user attributes for targeting in [Flags: User Segments](/flags/targeting-and-rollouts#user-segments). * See [User Context Identification](#user-context-identification) for the recommended approach to building the context. ```typescript theme={null} const ctx: FsUserContext = { key: 'user-123', attributes: { plan: 'premium', country: 'US', userType: 'enterprise' } } ``` Ensure the `key` in `FsUserContext` is unique and persistent for accurate MAU tracking and consistent flag evaluations. See [User Context Best Practices](/sdks/overview#user-context-best-practices) for details. ### Flag Syncing Configure flag update strategies with the `sync` object: `ws`, `sse`, `poll`, or `off`. By default, flag updates propagate in milliseconds over a WebSocket connection, ensuring the latest values are used in evaluations. Stream updates over a WebSocket connection—flag updates are reevaluated on the server and pushed to the client in real time: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', sync: { type: 'ws' // Default } }); ``` Stream updates via server-sent events (SSE): ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', sync: { type: 'sse' } }); ``` Poll the server on an interval: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', sync: { type: 'poll', pollRateInSec: 60 } }); ``` Disable syncing: ```typescript theme={null} const factory = FlagSyncFactory({ sdkKey: 'your-sdk-key', sync: { type: 'off' } }); ``` ## Best Practices * Wait for SDK readiness before evaluating flags. * Select a sync strategy (`ws`/`sse`/`poll`/`off`) based on your application's needs. * Follow [User Context Identification](#user-context-identification) for simplified context management. * Add user attributes for targeted feature rollouts. ## Environment Variables Set the following environment variable: * `FLAGSYNC_SDK_KEY`: Your server-side FlagSync SDK key (required) # Overview Source: https://docs.flagsync.com/sdks-server-side/overview Learn about FlagSync’s server-side SDKs for multi-user contexts. ## Overview FlagSync’s server-side SDKs are designed for multi-user contexts like web servers and APIs: User segment targeting rule creation For Node.js-based servers and APIs. User segment targeting rule creation For Next.js-based server-side rendering (App Router). User segment targeting rule creation For Nest.js-based server applications. Need another language or framework? Contact FlagSync Support to explore adding it to our roadmap. ## Next Steps Get started with server-side SDKs: * Learn about client-side SDKs in [Client-Side SDKs](/sdks-client-side/overview). * Set up an SDK in [Setup](/sdks/setup). * Start with [Quickstart: SDK](/quickstarts/sdk). # Overview Source: https://docs.flagsync.com/sdks/overview Understand the key concepts of FlagSync SDKs for feature management. ## SDK Concepts FlagSync SDKs enable feature management across platforms: Learn the prerequisites and initialization process for SDKs. Explore client-side and server-side SDK differences. Understand how FlagSync evaluates flags for users. Learn how FlagSync CLI provides type safety in your application. ## SDK Best Practices The [FlagSync CLI](/sdks-cli/overview) generates TypeScript types from your feature flag config. * IntelliSense autocompletion (e.g., `client.flag(...)`, `useFlag(...)`) * Compile-time safety. * Confidence that your code matches your flags. ## User Context Best Practices When defining the user context for flag evaluations, always provide a unique and persistent `key` in the `FsUserContext` object to ensure accurate billing and consistent flag behavior: * **Billing Impact**: FlagSync tracks monthly active users (MAUs) based on unique `key` values, which are limited by your pricing tier. Non-unique or non-persistent keys (e.g., hardcoding `'anonymous'` or generating a new ID per request) can undercount or overcount MAUs, affecting billing accuracy. * **Functionality Impact**: During percentage rollouts, FlagSync uses the user context for deterministic hashing to ensure the same user receives consistent flag values across sessions. Non-persistent keys cause inconsistent flag evaluations, disrupting rollout behavior. Avoid hardcoding `key` values like `'anonymous'` or generating a new ID on every request (e.g., calling `nanoid()` without persistence). Instead, use a persistent identifier, such as a cookie for unauthenticated users (e.g., `visitor-id`), to ensure accurate MAU tracking and consistent flag evaluations. # Setup Source: https://docs.flagsync.com/sdks/setup Get started with FlagSync SDKs for your application. ## Getting Started with SDKs Check out the SDK examples at [https://github.com/flagsync/sdk-examples](https://github.com/flagsync/sdk-examples)! Choose client-side or server-side—e.g., web apps may need both for SSR. For single-user contexts (e.g., web/mobile apps). For multi-user contexts (e.g., web servers, APIs). FlagSync supports JavaScript in various forms:
User segment targeting rule creation

JavaScript

User segment targeting rule creation

React

User segment targeting rule creation

Node.js

User segment targeting rule creation

Next.js

User segment targeting rule creation

Nest.js

Contact FlagSync Support for other languages.
* Use **client-side** keys (`pk_test_ABC...`) for web/mobile apps. * Keep **server-side** keys (`sk_test_DEF...`) private to protect sensitive flag rules.
## Initialization * SDK initialization happens asynchronously—response time, usually 30-50 milliseconds, depends on flag count and ruleset complexity. * Use a singleton pattern to avoid memory leaks—SDKs like Nest.js handle this automatically; others require manual setup. Creating multiple instances can lead to memory leaks and orphaned connections. ## Next Steps Set up and explore FlagSync SDKs: * Learn SDK differences in [Types](/sdks/types). * Understand evaluation in [Flag Evaluation](/sdks-flag-evaluation/overview). * Start with [Quickstart: SDK](/quickstarts/sdk). # Types Source: https://docs.flagsync.com/sdks/types Learn the differences between FlagSync’s client-side and server-side SDKs. ## SDK Types FlagSync offers two SDK types for different environments: For single-user contexts (e.g., web/mobile apps). For multi-user contexts (e.g., web servers, APIs). ### Using Both SDK Types for SSR Apps SSR web apps often benefit from using both SDKs for seamless feature management. Server-side SDKs enable flag evaluation for redirects (e.g., rerouting if a feature is off) and tracking purchases, while passing flags to the UI to avoid client-side SDK calls. Meanwhile, client-side SDKs track events like `page_load_time` or button clicks, ensuring comprehensive data collection. This combination is not uncommon and offers server-side control and client-side tracking flexibility. ## Key Differences

Client-side SDKs require a user context at initialization.


Server-side SDKs initialize without one.

Client-side SDKs evaluate on FlagSync’s servers and send key-value pairs for the user to the client.


Server-side SDKs fetch full rulesets from FlagSync and evaluate locally at runtime.

## Next Steps Explore more about SDKs and flag evaluation: * Set up an SDK in [Setup](/sdks/setup). * Learn SDK targeting logic in [Targeting](/sdks-flag-evaluation/targeting). * Start with [Quickstart: SDK](/quickstarts/sdk).