Skip to content

ConfigTypes

Ahmed Abbas edited this page Apr 23, 2025 · 2 revisions

Chapter 10: Config / Types

Welcome to the final chapter! In Chapter 9: EventManager, we explored the SDK's internal intercom system, allowing different parts to communicate using events like READY or BUCKETING. We've seen how all the managers work together to run experiments and feature flags.

But how does the SDK know the exact structure of the data it receives from the Convert API? How does it know what an "Experience" object looks like, or what fields a "Goal" should have? And how can you tell the SDK how to behave when you first set it up (like how often it should check for updates, or how verbose its logging should be)?

The Problem: The Need for Blueprints and Instructions

Imagine trying to assemble a complex piece of furniture with only a bag of parts and no instructions or list of what parts should be there. It would be chaos! You need:

  1. A Parts List / Blueprint: To know what each part is, what it looks like, and how it fits with others.
  2. Assembly Instructions: To know how to put the parts together and any settings you can adjust (like shelf height).

The Convert SDK needs the same things:

  1. Blueprints (Types): It needs precise definitions for all the data structures it works with – Experiences, Features, Audiences, Goals, Variations, etc. This ensures consistency and prevents errors.
  2. Instructions (Config): You need a way to give the SDK initial setup instructions when you create it, telling it things like your project's unique key (sdkKey), how to handle data storage, and how often to communicate with Convert servers.

How does the SDK handle these blueprints and instructions?

What are "Types"? The SDK's Data Dictionary

Think of Types as the detailed blueprints or the official dictionary for all the data used within the Convert SDK. They define the shape and kind of data for every entity.

  • Structure: A Type definition tells you exactly what fields an object should have. For example, the type definition for an Experience might specify that it must have an id (string), a key (string), a name (string), and it can have variations (an array of Variation objects) and audiences (an array of strings), etc.
  • Data Kind: It also defines what kind of data each field holds (e.g., id is a string, traffic_allocation in a Variation is a number, is_default in Project settings is a boolean - true/false).
  • Consistency: By using these predefined Types, every part of the SDK agrees on what an "Experience" or a "Goal" looks like. The DataManager knows what structure to expect when receiving data, and the ExperienceManager knows what fields it can reliably access on an Experience object.

Where do these Types come from?

These Types are not just made up! They are automatically generated based on the official Convert API definition (specifically, the OpenAPI specification). This ensures that the SDK's understanding of data structures perfectly matches the data sent by the Convert servers.

You can find these generated type definitions primarily in the packages/types/src/config/types.gen.ts file within the SDK's source code.

Example: A Simplified Type (Conceptual)

Let's imagine a very simplified TypeScript definition for an Experience object:

// Conceptual Example - actual types are more detailed

interface SimpleExperienceType {
  id: string;         // Must have an ID, which is text
  key: string;        // Must have a key, which is text
  name: string;       // Must have a name, text
  status: 'active' | 'paused' | 'draft'; // Status must be one of these specific text values
  variations?: Array<SimpleVariationType>; // Optional list of variations
  audiences?: Array<string>;            // Optional list of audience IDs (text)
}

interface SimpleVariationType {
  id: string;
  key: string;
  traffic_allocation: number; // Must be a number (e.g., 5000 for 50%)
}
  • This interface acts as a blueprint. Any object claiming to be a SimpleExperienceType must adhere to this structure.
  • The ? means a field is optional (like variations or audiences).
  • Array<SimpleVariationType> means it's a list where each item follows the SimpleVariationType blueprint.

You don't usually interact with these type definitions directly, but they are crucial for the SDK's internal consistency and for understanding the data you might receive from methods like context.runExperience().

What is the "Config" Object? Your Instructions to the SDK

While Types define the data structures, the Config object provides the initial setup instructions you give to the SDK when you create it. It's the main way you customize the SDK's behavior.

Remember this from Chapter 1: ConvertSDK / Core?

import ConvertSDK from '@convertcom/js-sdk';

// THIS is the Config object!
const config = {
  sdkKey: 'YOUR_SDK_KEY', // Tells the SDK which project to load
  dataRefreshInterval: 600000, // Check for updates every 10 minutes (600,000 ms)
  logger: {
    logLevel: 'info' // Set logging level to 'info'
  },
  dataStore: window.localStorage // Use browser localStorage for visitor data persistence
};

const convert = new ConvertSDK(config);
  • The config variable holds a Javascript object containing key-value pairs.
  • These pairs tell the ConvertSDK constructor how to configure itself.

Common Configuration Options:

Here are some important settings you can control (defined by the Config type in packages/types/src/Config.ts):

  • sdkKey (string): Required if not providing data. Your unique project identifier from Convert. Tells the SDK to fetch configuration from the API. (Chapter 8: ApiManager)
  • data (object): Required if not providing sdkKey. Allows you to provide the entire project configuration JSON directly, bypassing the API fetch.
  • dataStore (object | null): How the SDK should remember visitor bucketing decisions across sessions. You can pass objects compatible with getItem/setItem like window.localStorage, window.sessionStorage, or a custom cookie handler. If null (default), decisions are only kept in memory for the current session. (Chapter 5: DataManager)
  • dataRefreshInterval (number): How often (in milliseconds) the SDK should automatically check for updated project configuration from the API. Default is usually 5 minutes (300,000 ms). (Chapter 8: ApiManager)
  • events (object): Settings for batching tracking events:
    • batch_size (number): How many events to collect before sending. (Default: 10)
    • release_interval (number): Max time (in ms) to wait before sending, even if batch isn't full. (Default: 1000ms)
    • (Chapter 8: ApiManager)
  • logger (object): Controls console logging:
    • logLevel (string): Sets the minimum level to log (e.g., 'debug', 'info', 'warn', 'error', 'silent').
    • customLoggers (array): Allows adding custom logging destinations.
  • rules (object): Advanced customization for how targeting rules are processed. (Chapter 7: RuleManager)
  • bucketing (object): Advanced customization for the hashing algorithm. (Chapter 6: BucketingManager)
  • network.tracking (boolean): Set to false to disable sending tracking events to Convert (useful for testing without affecting reports). Default is true.

You provide the options you need in the Config object, and the SDK uses them during its setup.

Under the Hood: Processing Config and Using Types

1. Processing the Config Object:

When you call new ConvertSDK(config), the SDK doesn't just use your provided config object directly. It merges your settings with a set of default values.

  • There's a defaultConfig object defined (see packages/js-sdk/src/config/default.ts) that contains standard values for all settings.
  • A helper function (called Config in packages/js-sdk/src/config.ts) takes your provided config and merges it on top of the defaultConfig. This means you only need to specify the settings you want to change from the defaults.
// Simplified logic from packages/js-sdk/src/config.ts

import { defaultConfig } from './config/default';
import { objectDeepMerge } from '@convertcom/js-sdk-utils'; // Merging utility

// Default settings (example)
const DEFAULT_LOGGER_SETTINGS = { logger: { logLevel: 'warn' } };

// Function that processes the config
export const Config = (userProvidedConfig = {}) => {
  // Merge user settings over defaults
  const finalConfiguration = objectDeepMerge(
    DEFAULT_LOGGER_SETTINGS, // Base defaults
    defaultConfig,          // More defaults
    userProvidedConfig      // Your settings override defaults
  );
  return finalConfiguration; // The final, complete config object
};

// When you do 'new ConvertSDK(myConfig)', internally it does something like:
// const finalConfig = Config(myConfig);
// // ... then uses finalConfig to set up managers ...
  • This merging ensures the SDK always has a valid value for every setting.

2. Using Types Internally:

Throughout the SDK, when components handle data, they rely on the defined Types.

  • When the ApiManager fetches data, the DataManager expects the result to match the ConfigResponseData type.
  • When the ExperienceManager needs details about an experiment, it asks the DataManager using getEntity(key, 'experiences'). The DataManager returns an object, and the ExperienceManager trusts that this object conforms to the ConfigExperience type, allowing it to safely access properties like experience.variations or experience.status.
// Conceptual code inside ExperienceManager

import { ConfigExperience } from '@convertcom/js-sdk-types'; // Import the type blueprint
import { DataManagerInterface } from '@convertcom/js-sdk-data';

class ExperienceManager {
  private _dataManager: DataManagerInterface;
  // ... constructor ...

  getExperienceStatus(key: string): string | null {
    // Ask DataManager for the experience object
    const experience = this._dataManager.getEntity(key, 'experiences');

    // Because we trust the type system, we know 'experience' (if found)
    // will have a 'status' property conforming to the ConfigExperience type.
    if (experience) {
      // Type safety: We can access 'status' with confidence.
      return (experience as ConfigExperience).status;
    }
    return null;
  }
}
  • Using Types provides structure and helps prevent bugs caused by accessing non-existent properties or using data of the wrong kind.

Conclusion

Configuration and Types are the foundation upon which the Convert SDK is built.

  • Types act as the blueprints or dictionary, defining the structure and kind of data for all entities (Experiences, Features, Goals, etc.), ensuring internal consistency. They are auto-generated from the Convert API specification.
  • The Config object is your instruction manual, allowing you to customize the SDK's behavior during initialization by providing settings like your sdkKey, dataStore, dataRefreshInterval, logging levels, and more.

Understanding these concepts helps you effectively configure the SDK for your specific needs and interpret the data structures it uses and returns.

This chapter concludes our journey through the core concepts and components of the Convert Javascript SDK. You've learned about the main entry point (ConvertSDK / Core), visitor sessions (Context), managing tests (ExperienceManager) and features (FeatureManager), data handling (DataManager), traffic splitting (BucketingManager), rule evaluation (RuleManager), API communication (ApiManager), internal notifications (EventManager), and finally, the underlying structure and settings (Config / Types).

We hope this tour has given you a solid understanding of how the SDK works and how you can use it effectively in your projects!

Clone this wiki locally