Skip to main content

LaunchDarkly + DataGrail Consent

LaunchDarkly is a feature flag and experimentation platform with a critical distinction for consent: server-side feature flags require no consent, while client-side SDK + experimentation require consent. This guide helps you choose the right approach for your compliance needs.

Server-Side vs Client-Side

Understanding the difference between server-side and client-side evaluation is essential for consent compliance:

Evaluation TypeBrowser Storage?Network Calls?Consent Required?Use Case
Server-SideNoneNone from browserNoFeature flags evaluated on your backend
Client-Side (events off)localStorageStreaming connectionLikely (Functional)Real-time flags with minimal tracking
Client-Side (events on)localStorageEvents + streamingYes (Performance)Flags with analytics/experimentation
ExperimentationlocalStorageFull event trackingYes (Performance)A/B testing with conversion tracking
Prefer Server-Side for Zero Consent

If your primary use case is feature flags (not experimentation), use LaunchDarkly's server-side SDK. Your backend evaluates flags and passes the results to your frontend — no browser storage, no consent requirement.

Gated Client SDK

For client-side experimentation, gate SDK initialization behind DataGrail's callbacks:

<script>
window.dgEvent = window.dgEvent || [];

function initLaunchDarkly(preferences) {
if (window.DG_BANNER_API.categoryEnabled('performance') && !window.ldClient) {
var context = {
kind: 'user',
key: 'user-unique-id',
email: 'user@example.com'
};

var options = {
sendEvents: true,
fetchGoals: true
};

window.ldClient = LDClient.initialize('YOUR_CLIENT_ID', context, options);

window.ldClient.waitForInitialization().then(function() {
var showFeature = window.ldClient.variation('feature-flag-key', false);
});
}
}

window.dgEvent.push({
event: "initial_preference_callback",
params: initLaunchDarkly
});

window.dgEvent.push({
event: "preference_callback",
params: initLaunchDarkly
});
</script>

Server-Side Only

Evaluate flags on your backend and pass flag states to your frontend:

// Backend (Node.js example)
const client = LaunchDarkly.init('YOUR_SERVER_SDK_KEY');

app.get('/api/flags', async (req, res) => {
const context = {
kind: 'user',
key: req.user.id
};

const flags = await client.allFlagsState(context);
res.json(flags.toJSON());
});
// Frontend - no LaunchDarkly SDK, just use flag values from API
fetch('/api/flags')
.then(response => response.json())
.then(flags => {
if (flags['feature-flag-key']) {
// Show feature
}
});

Advantages:

  • No browser storage required
  • No consent requirement for feature flags
  • Reduced client-side JavaScript
  • Better security (server controls evaluation rules)

Limited Tracking Mode

If you need real-time flag updates but want to minimize tracking, initialize with events disabled when only Functional consent is granted:

<script>
window.dgEvent = window.dgEvent || [];

function initLaunchDarklyLimited(preferences) {
if (!window.ldClient && window.DG_BANNER_API.categoryEnabled('functional')) {
window.ldClient = LDClient.initialize('YOUR_CLIENT_ID', context, {
sendEvents: false,
fetchGoals: false
});
}
}

window.dgEvent.push({
event: "initial_preference_callback",
params: initLaunchDarklyLimited
});
</script>

This approach uses localStorage for caching but sends no behavioral data to LaunchDarkly.

Storage Patterns

LaunchDarkly exclusively uses localStorage — no cookies are set. Since DataGrail's Cookie Management manages cookie rules, the primary enforcement mechanism for LaunchDarkly is gating SDK initialization behind consent as shown in the patterns above.

LaunchDarkly Uses No Cookies

LaunchDarkly stores data in localStorage under keys prefixed with LaunchDarkly_. Because no cookies are written, there are no cookie rules to add in the DataGrail dashboard. Instead, control access by only initializing the SDK after consent is granted.

Experimentation Tracking

LaunchDarkly Experimentation tracks these event types:

  • feature events — Flag evaluation context
  • click events — Element interactions
  • page view events — URL visits
  • custom events — Conversion goals you define
  • summary events — Aggregated flag evaluations

All experimentation tracking requires Performance consent. Use the sendEvents and fetchGoals options to control tracking:

<script>
window.dgEvent = window.dgEvent || [];

function initLaunchDarklyTiered(preferences) {
if (window.ldClient) return;
var context = { kind: 'user', key: 'anonymous-user' };

if (window.DG_BANNER_API.categoryEnabled('performance')) {
window.ldClient = LDClient.initialize('YOUR_CLIENT_ID', context, {
sendEvents: true,
fetchGoals: true
});
} else if (window.DG_BANNER_API.categoryEnabled('functional')) {
window.ldClient = LDClient.initialize('YOUR_CLIENT_ID', context, {
sendEvents: false,
fetchGoals: false
});
}
}

window.dgEvent.push({
event: "initial_preference_callback",
params: initLaunchDarklyTiered
});

window.dgEvent.push({
event: "preference_callback",
params: initLaunchDarklyTiered
});
</script>

Enforcement Strategy

Since LaunchDarkly uses localStorage rather than cookies, the best enforcement strategy is to gate SDK initialization behind consent callbacks rather than trying to block storage. The patterns in the Recommended Approaches section show how to only initialize the client SDK after the appropriate consent category is granted.

Privacy Controls

LaunchDarkly provides these privacy controls you can combine with DataGrail consent:

ControlPurposeUse Case
sendEvents: falseDisables all analyticsFlags without measurement
fetchGoals: falseDisables experimentation metricsFlags without experiments
privateAttributesPrevents specific fields from being storedMask PII in context
eventUrlTransformerRedacts URLs in eventsRemove sensitive query params
EU endpointsUses .eu.launchdarkly.comData residency requirements

Here's how to classify LaunchDarkly based on your usage:

Your UsageSuggested CategoryDataGrail Action
Server-side flags onlyStrictly NecessaryNo consent required
Client SDK for flags (no events)FunctionalGate initialization behind functional consent
Client SDK with experimentationPerformanceGate initialization behind performance consent
Session Replay enabledPerformanceRequires explicit performance consent

Troubleshooting

LaunchDarkly SDK initializes before consent is collected

Ensure:

  • You're not initializing the SDK in a global script
  • SDK initialization is inside your initial_preference_callback or preference_callback handler
  • You're checking window.DG_BANNER_API.categoryEnabled('performance') before initializing
  • The DataGrail banner script loads before your callback registration
Feature flags don't update in real-time

This usually means:

  • You're using server-side evaluation without a streaming connection
  • Client SDK isn't initialized (consent not granted)
  • Streaming connection is blocked by a firewall/proxy
  • You need to reload flag state from your backend API
localStorage blocked errors in browser console

This is expected behavior when:

  • DataGrail is blocking localStorage until consent
  • User has denied consent but your code is trying to initialize SDK
  • Solution: Only initialize SDK after confirming consent is granted
Want flags immediately but experimentation gated

Use the two-tier approach:

  1. Server-side evaluation provides flag values on page load (no consent needed)
  2. Client SDK initializes after consent for experimentation only
  3. Flags work immediately; tracking starts post-consent

LaunchDarkly v4 Breaking Changes

If you're using LaunchDarkly JS SDK v4.x or later:

  • localStorage caching is ON by default (was opt-in in v3)
  • DNT (Do Not Track) support was REMOVED — you must implement consent gating manually
  • Device ID (ld_device context key) is automatically generated and persisted

These changes make v4 more reliant on consent management than v3. Ensure you're properly gating SDK initialization.

 

Need help?
If you have any questions, please reach out to your dedicated Account Manager or contact us at support@datagrail.io.

Disclaimer: The information contained in this message does not constitute as legal advice. We would advise seeking professional counsel before acting on or interpreting any material.