Dev guideAPI Reference
Dev guideAPI ReferenceUser GuideGitHubNuGetDev CommunityDoc feedbackLog In

OptimizelyConfig

This topic describes 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, e := optimizelyFactory.Client()
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)