The availability of features may depend on your plan type. Contact your Customer Success Manager if you have any questions.

Dev guideRecipesAPI Reference
Dev guideAPI ReferenceUser GuideLegal TermsGitHubDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

OptimizelyConfig for the Go SDK

How to get access to project configuration data within the datafile using OptimizelyConfig. for the Optimizely Feature Experimentation Go SDK.

Overview

Optimizely Feature Experimentation SDKs open a well-defined set of public APIs, hiding all implementation details. However, some clients may need access to project configuration data within the datafile.

In this document, we extend our public APIs to define data models and access methods, which clients can use to access project configuration data.

OptimizelyConfig API

A public configuration data model (OptimizelyConfig) is defined below as a structured format of static Optimizely Project data.

Get OptimizelyConfig

OptimizelyConfig can be accessed from OptimizelyClient (top-level) with this public API call:

client, err := optimizelyFactory.Client()
if err != nil {
	// handler error
}
var config = client.GetOptimizelyConfig()

getOptimizelyConfig returns an OptimizelyConfig instance, which includes

  • environment key
  • SDK key
  • the datafile revision number
  • all experiments mapped by their key values
  • all attributes
  • all audiences
  • all events
  • feature flags mapped by their key values
  • function to retrieve the project configuration (the datafile)

📘

Note

When the SDK datafile is updated (the client can add a notification listener for ProjectConfigUpdateNotification to get notified), the client is expected to call the method to get the updated OptimizelyConfig data. See examples below.

Get datafile

To share the same datafile between multiple SDK instances (for example, in a client/server scenario), you can pass a JSON string representation of the config (the datafile) between the instances. To get the datafile, use the OptimizelyConfig object's GetDatafile method. For more information, see Sharing the datafile with multiple SDK implementations.

Object model

The following shows the object model for OptimizelyConfig.

type OptimizelyConfig struct {
	EnvironmentKey string
	SdkKey         string
	Revision       string

	// This experimentsMap is for experiments of legacy projects only.
	// For flag projects, experiment keys are not guaranteed to be unique
	// across multiple flags, so this map may not include all experiments
	// when keys conflict.
	ExperimentsMap map[string]OptimizelyExperiment

	FeaturesMap map[string]OptimizelyFeature
	Attributes  []OptimizelyAttribute
	Audiences   []OptimizelyAudience
	Events      []OptimizelyEvent
}

type OptimizelyExperiment struct {
	ID            string
	Key           string
	Audiences     string
	VariationsMap map[string]OptimizelyVariation
}

type OptimizelyFeature struct {
	ID              string
	Key             string
	ExperimentRules []OptimizelyExperiment
	DeliveryRules   []OptimizelyExperiment
	VariablesMap    map[string]OptimizelyVariable

	// Deprecated: Use experimentRules and deliveryRules
	ExperimentsMap map[string]OptimizelyExperiment
}

type OptimizelyVariation struct {
	ID             string
	Key            string
	FeatureEnabled bool
	VariablesMap   map[string]OptimizelyVariable
}

type OptimizelyVariable struct {
	ID    string
	Key   string
	Type  string
	Value string
}

type OptimizelyAttribute struct {
	ID  string
	Key string
}

type OptimizelyAudience struct {
	ID         string
	Name       string
	Conditions string
}

type OptimizelyEvent struct {
	ID            string
	Key           string
	ExperimentIds []string
}

Examples

OptimizelyConfig can be accessed from OptimizelyClient (top-level) like this:

optimizelyConfig := optimizelyClient.GetOptimizelyConfig()

	fmt.Println("[OptimizelyConfig] revision = " + optimizelyConfig.Revision)
	fmt.Println("[OptimizelyConfig] sdkKey = " + optimizelyConfig.SdkKey)
	fmt.Println("[OptimizelyConfig] environmentKey = " + optimizelyConfig.EnvironmentKey)

	fmt.Println("[OptimizelyConfig] attributes:")
	for _, attribute := range optimizelyConfig.Attributes {
		fmt.Println("[OptimizelyAttribute]   -- (id, key) = " + attribute.ID + ", " + attribute.Key)
	}
	fmt.Println("[OptimizelyConfig] audiences:")
	for _, audience := range optimizelyConfig.Audiences {
		fmt.Println("[OptimizelyAudience]   -- (id, name, conditions) = " + audience.ID + ", " + audience.Name + ", " + audience.Conditions)
	}
	fmt.Println("[OptimizelyConfig] events:")
	for _, event := range optimizelyConfig.Events {
		fmt.Println(fmt.Sprintf("[OptimizelyEvent]   -- (id, key, experimentIds) = %s, %s, %v", event.ID, event.Key, event.ExperimentIds))
	}

	// all flags
	flagKeys := []string{}
	for flagKey := range optimizelyConfig.FeaturesMap {
		flagKeys = append(flagKeys, flagKey)
	}

	for _, flagKey := range flagKeys {
		flag := optimizelyConfig.FeaturesMap[flagKey]

		experimentRules := flag.ExperimentRules
		deliveryRules := flag.DeliveryRules

		// use experiment rules and delivery rules and other flag data here...

		for _, experiment := range experimentRules {
			fmt.Println("[OptimizelyExperiment]   - experiment rule-key = " + experiment.Key)
			fmt.Println("[OptimizelyExperiment]   - experiment audiences = " + experiment.Audiences)

			variationKeys := []string{}
			variationsMap := experiment.VariationsMap
			for variationKey, _ := range variationsMap {
				variationKeys = append(variationKeys, variationKey)
			}

			for _, varKey := range variationKeys {
				variation := variationsMap[varKey]
				fmt.Println(fmt.Sprintf("OptimizelyVariation]       -- variation = { key: %s, id: %s, featureEnabled: %v }", varKey, variation.ID, variation.FeatureEnabled))

				variablesMap := variationsMap[varKey].VariablesMap
				variableKeys := []string{}

				for variableKey := range variablesMap {
					variableKeys = append(variableKeys, variableKey)
				}

				for _, variableKey := range variableKeys {
					variable := variablesMap[variableKey]

					fmt.Println(fmt.Sprintf("[OptimizelyVariable]           --- variable: %s, %v", variableKey, variable))
				}
			}
		}

		for _, delivery := range deliveryRules {
			fmt.Println("[OptimizelyExperiment]   - delivery rule-key = " + delivery.Key)
			fmt.Println("[OptimizelyExperiment]   - delivery audiences = " + delivery.Audiences)

			// use delivery rule data here...
		}
	}

	// listen to NotificationType.datafileChange to get updated data
	callback := func(notification notification.ProjectConfigUpdateNotification) {
		var newOptConfig = optimizelyClient.GetOptimizelyConfig()
		fmt.Println("[OptimizelyConfig] revision = " + newOptConfig.Revision)
	}
	optimizelyClient.ConfigManager.OnProjectConfigUpdate(callback)