Optimizely's SDKs provide a general interface for running experiments throughout your applications and services. Because you'll likely have many teams running experiments in different parts of your stack with varying requirements, we've designed Full Stack for maximum customization. You use _projects_, _environments_, _datafiles_, and _clients_ to adapt a Full Stack SDK to your developmental workflow.
A Full Stack project lets you isolate each of your teams or applications in their own separate shared workspace. Projects are where a team builds experiments, manages feature flags, defines target audiences, and more. Each project has its own set of permissions.
Projects have a many-to-many relationship with your application stack. You can have many different projects to manage different parts of a single application, or use a single project to manage omni-channel experiments across your website backend and mobile app.
Because your account already includes a project, [creating another project](🔗) is an optional step.
Use [environments](🔗) in Optimizely to develop and validate your experiment internally before displaying changes to your production website, whether you use a formal deployment environment or not. Each project can have one or more environments.
For example, it's common to set up both staging and production environments in Optimizely. You'll often develop and [QA your experiments](🔗) in staging, and deploy to production when you're ready. You can set up different permissions for who can make changes in each of these environments.
Each environment in a project has a corresponding datafile. This file captures the configuration data of all your experiments, such as feature flags and event tracking, in a JSON format. When you make changes in a project, each environment's datafile is automatically updated with the new configuration. By [synchronizing](🔗) a local copy of this datafile, the SDK can run experiments without making blocking network requests to an outside API.
Optimizely generates a different version of the datafile for each environment you configure on your account. This allows you to toggle a feature flag in one environment while keeping it paused in another. You don't need to duplicate your code, your Optimizely project, or experiments within your project.
A client is an instance of the Optimizely SDK running with a specific datafile and other configuration settings. To use the SDK, [get the appropriate datafile](🔗) and then [instantiate a client](🔗) with it. This client exposes all the methods you need to `
activate` experiments, `
track` events, and perform other tasks.
The iOS and Android SDKs (also called the _mobile SDKs_) offer the additional abstraction of a client **manager**. The manager handles synchronizing datafiles and generating the associated clients for you, along with other optimizations around event dispatching and persisting user state on the device. Using the manager is optional, and you can instantiate a client directly if you prefer complete control. If you're using the iOS SDK or Android SDK, see [Initialize a mobile SDK](🔗).
An impression is a unit of measurement of usage. In Full Stack, Optimizely counts an impression each time an experiment is activated and a decision event is sent. See [Manage impressions](🔗) for more information about:
When we send impressions and when we don't.
How we use impressions to calculate data for the Results page and keep track of your account's impression quota.
Which method to use to generate or not generate impressions for certain use cases.
Our KB article [What is an impression in Optimizely](🔗) provides additional information about impressions, including the differences between how impressions are counted in Full Stack versus Web.