# Reference

## Start SDK

To initialize and start the SDK, just call the `start()` function of the `Flagship` class in the most appropriate location for your application.

#### **`def start(env_id, api_key, configuration=None)`**

```python
from flagship import Flagship

Flagship.start('_YOUR_ENV_ID_', '_YOUR_API_KEY_')
```

| Parameter     | Required | Type                                     | Description                                       |
| ------------- | -------- | ---------------------------------------- | ------------------------------------------------- |
| env\_id       | Yes      | str                                      | Environment id provided by Flagship.              |
| api\_key      | Yes      | str                                      | Api authentication key provided by Flagship.      |
| configuration | No       | DecisionApi / Bucketing (FLagshipConfig) | Flagship configuration (DecisionApi or Bucketing) |

{% hint style="info" %}
📘 Info

You can find your `env_id` and your `api_key` on your Flagship account, in Parameters > Environment & Security.
{% endhint %}

***

## Configure your Python SDK

These classes aim to help you to configure the SDK via the following two available config implementations: DecisionApi and Bucketing.

### DecisionApi (default)

Run the SDK in DecisionApi mode. The campaign assignments and targeting validation take place server-side. In this mode, each call to the fetchFlags method to refresh the flags will create an HTTP request.

```python
from flagship import Flagship
from flagship.config import DecisionApi

Flagship.start('_YOUR_ENV_ID_', '_YOUR_API_KEY_', DecisionApi(
  timeout=3000,
  log_level=LogLevel.ALL,
  status_listener=CustomStatusListener(),
  log_manager=CustomLogManager()
))
```

| Kwarg parameter           | Type                  | Default                         | Description                                                                                                                                                                                                                    |
| ------------------------- | --------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| timeout                   | int                   | 2000                            | Specifies timeout for decision api requests in milliseconds                                                                                                                                                                    |
| log\_level                | LogLevel              | LogLevel.ALL                    | Specifies a log level to filter logs emitted by the SDK.                                                                                                                                                                       |
| status\_listener          | StatusListener        | None                            | Specifies a callback to be notified when the SDK status has changed.                                                                                                                                                           |
| log\_manager              | LogManager            | FlagshipLogManager              | Specifies a custom implementation of LogManager in order to receive logs from the SDK.                                                                                                                                         |
| tracking\_manager\_config | TrackingManagerConfig | Default Tracking Manager Config | Specifies a custom tracking manager configuration. **See** [**TrackingManagerConfig**](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#tracking-manager-configuration) **section** |
| cache\_manager            | CacheManager          | None                            | Specifies a custom cache manager implementation. **See** [**CacheManager**](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#manage-sdk-cache) **section**                          |

### Bucketing

When the SDK is running in Bucketing mode, the SDK downloads all the campaigns configurations at once in a single bucketing file so that variation assignment can be computed client-side by the SDK. This bucketing file is stored in cache and will only be downloaded again when campaign configurations are modified in the Flagship interface.

```python
from flagship import Flagship
from flagship.config import Bucketing

Flagship.start('_YOUR_ENV_ID_', '_YOUR_API_KEY_', Bucketing(
  timeout=3000,
  log_level=LogLevel.ALL,
  status_listener=CustomStatusListener(),
  polling_interval=2000,
  log_manager=CustomLogManager()
))
```

| Kwarg parameter           | Type                  | Default                         | Description                                                                                                                                                                                                                    |
| ------------------------- | --------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| timeout                   | int                   | 2000ms                          | Specifies timeout for decision api requests in milliseconds                                                                                                                                                                    |
| log\_level                | LogLevel              | LogLevel.ALL                    | Specifies a log level to filter logs emitted by the SDK.                                                                                                                                                                       |
| status\_listener          | StatusListener        | None                            | Specifies a callback to be notified when the SDK status has changed.                                                                                                                                                           |
| log\_manager              | LogManager            | FlagshipLogManager              | Specifies a custom implementation of LogManager in order to receive logs from the SDK.                                                                                                                                         |
| polling\_interval         | int                   | 60000ms                         | Defines the time interval between two bucketing updates in milliseconds.                                                                                                                                                       |
| tracking\_manager\_config | TrackingManagerConfig | Default Tracking Manager Config | Specifies a custom tracking manager configuration. **See** [**TrackingManagerConfig**](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#tracking-manager-configuration) **section** |
| cache\_manager            | CacheManager          | None                            | Specifies a custom cache manager implementation. **See** [**CacheManager**](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#manage-sdk-cache) **section**                          |

***

## Create new visitors

The `visitor` instance is an helper object that lets you manage the context and campaigns for a visitor identified by a unique ID.

The visitor context is a property dataset that defines the current visitor of your app. This dataset is sent and used by the Flagship Decision API or the SDK as targeting criteria for campaign assignments.

For example, if you want to enable or disable a specific feature based on VIP status, you would pass this attribute as a key-value pair in the visitor context so that the Decision API can enable or disable the corresponding feature flag for the user.

#### **`def new_visitor(visitor_id, **kwargs)`**

```python
visitor = Flagship.new_visitor('your_visitor_unique_id',
                               instance_type=Visitor.Instance.NEW_INSTANCE,
                               authenticated=True,
                               consent=True,
                               context={
                                 'vip':True
                               }
                              )
```

| Parameter      | Required/optional | Type     | Default       | Description                                                                                                                                                                                                                                                                                                                                            |
| -------------- | ----------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| visitor\_id    | Required          | String   | /             | Visitor unique identifier                                                                                                                                                                                                                                                                                                                              |
| **Kwargs**     |                   |          |               |                                                                                                                                                                                                                                                                                                                                                        |
| instance\_type | optional          | Instance | NEW\_INSTANCE | This class specifies how Flagship SDK should handle the newly created visitor instance. See [Visitor.Instance](/server-side/sdks/python/python-reference.md)                                                                                                                                                                                           |
| authenticated  | optional          | Bool     | False         | Bool that Specifies if the visitor is authenticated (True) or anonymous (False). See [Keep experience continuity](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#keep-visitors-experience-continuity)                                                                                                     |
| consent        | optional          | Bool     | True          | Bool that Specifies if the visitor has consented for personal data usage. When false some features will be deactivated, cache will be deactivated and cleared.                                                                                                                                                                                         |
| context        | optional          | Dict     | {}            | Dict that specifies visitor initial context key / values used for targeting. Context keys must be String, and values types must be one of the following : Number, Boolean, String. See [Managing visitor context](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#target-visitors-by-updating-its-context) |

### Visitor Instance

Visitor.Instance is an enum class that help you to define how the SDK should handle the visitor reference. There are two types:

| Visitor.Intance  | Description                                                                                                                                                                                                                                  |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| SINGLE\_INSTANCE | The newly created visitor instance will be returned and saved into the Flagship singleton. Call Flagship.getVisitor() to retrieve the instance. This option should be adopted on applications that handle only one visitor at the same time. |
| NEW\_INSTANCE    | The newly created visitor instance wont be saved and will simply be returned. Any previous visitor instance will have to be recreated. This option should be adopted on applications that handle multiple visitors at the same time.         |

### Manage visitor consent

The Visitor class provides a method to let you manage visitor consent for data privacy usage. When False, ***campaign exposition*** and ***hits*** will be disabled and cache cleared until consent is passed True again.

#### **`def set_consent(self, consent)`**

```python
visitor.set_consent(True)
```

| Parameter | Required/optional |   | Type | Description                                                                                                                                        |
| --------- | ----------------- | - | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| consent   | Required          |   | Bool | Specify if the visitor has consented for personal data usage. When false some features will be deactivated, cache will be deactivated and cleared. |

{% hint style="warning" %}
🚧 Consent hits

Consent hit requests will still be enabled in order to clear server-side cached data.
{% endhint %}

***

## Target visitors by updating its context

The user context is a property dataset that defines the current user of your app. This dataset is sent and used by the Flagship Decision API or by the SDK in Bucketing mode as targeting criteria for campaign assignment.

The following method from the `visitor` instance allows you to set new context values matching the given keys.

```python
from flagship import Flagship, Visitor

#It is possible to pass initial context at visitor creation.

visitor = Flagship.new_visitor('your_visitor_unique_id', context={'vip':True})

#Later it is possible to update visitor context when you have more information.

last_purchase_info = {
	'last_purchase_date':'07-04-2023',
	'last_purchase_amount':99.9
}

visitor.update_context(last_purchase_info)

#Once the context is updated, you need to fetch the flags again so campaign assignments
# are also updated.

visitor.fetch_flags()
```

#### **`def update_context(self, context)`**

| Parameter | Required/optional | Type       | Description                                                                                                                                                                                                                                                                       |
| --------- | ----------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| context   | Required          | Tuple/Dict | Update the visitor context values, matching the given keys, used for targeting. A new context value associated with this key will be created if there is no previous matching value. Context keys must be Str, and values types must be one of the following : Number, Bool, Str. |

{% hint style="info" %}
🚧 Fetch flags

It is necessary to call **fetch\_flags()** method after having the new context updated so campaigns will also be updated accordingly.
{% endhint %}

### Predefined visitor context keys

The Flagship SDK contains predefined user context keys so the Flagship plateform will be able to recognize them.

You can overwrite these keys at any time, only the ones starting by 'FLAGSHIP' are reserved and cant be overridden.

All possible predefined keys are contained in the **FlagshipContext** enum class and are listed below:

| Key                  | Type       | Description                                                                        |
| -------------------- | ---------- | ---------------------------------------------------------------------------------- |
| DEVICE\_LOCALE       | str        | Define the current device locale in the visitor context. (must be a iso3 code str) |
| DEVICE\_TYPE         | DeviceType | Define the current device type in the visitor context.                             |
| DEVICE\_MODEL        | str        | Define the current device model (Google Pixel 3) in the visitor context            |
| LOCATION\_CITY       | str        | Define the current city location in the visitor context.                           |
| LOCATION\_REGION     | str        | Define the current region location in the visitor context.                         |
| LOCATION\_COUNTRY    | str        | Define the current country location in the visitor context.                        |
| LOCATION\_LAT        | float      | Define the current latitude location in the visitor context.                       |
| LOCATION\_LONG       | float      | Define the current longitude location in the visitor context.                      |
| OS\_NAME             | str        | Define the current OS name in the visitor context.                                 |
| OS\_VERSION          | str        | Define the current OS version name in the visitor context.                         |
| CARRIER\_NAME        | str        | Define the current carrier name in the visitor context.                            |
| INTERNET\_CONNECTION | str        | Define the current connection type (ex Edge/3G/4G/5G/Wifi) in the visitor context. |
| APP\_VERSION\_NAME   | str        | Define the current app version in the visitor context.                             |
| APP\_VERSION\_CODE   | int        | Define the current app version in the visitor context.                             |
| INTERFACE\_NAME      | str        | Define the current interface name or URL in the visitor context.                   |
| FLAGSHIP\_CLIENT     | str        | **Reserved by Flagship.** Specifies the current client SDK stack.                  |
| FLAGSHIP\_VERSION    | str        | **Reserved by Flagship.** Specifies the current version of the SDK.                |

***

## Fetch flags

The `fetch_flags()` method of the `visitor` instance automatically updates the campaign assignments according to the current user context, retrieves applicable flags and store them in the visitor instance.

When the SDK is configured with the [DecisionApi](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#decisionapi-default) decision mode, flags will be fetched from the Flagship Decision API via an http request. When configured with [Bucketing](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#bucketing) decision mode, flags will be fetched locally via de decision file.

#### **`def fetch_flags(self)`**

```python
from flagship import Flagship, Visitor

visitor = Flagship.new_visitor('your_visitor_unique_id', context={'vip':true})

# Get the flags from assigned campaign that match the given visitor context.
visitor.fetch_flags()
```

***

## Use your flags

Once the campaign has been **assigned** and **fetched**, all the flags are stored in the SDK. You can retrieve these flags using the following `get_flag` function from the `Visitor` instance:

#### **`def get_flag(self, key, default)`**

```python
from flagship import Flagship, Visitor

visitor = Flagship.new_visitor('your_visitor_unique_id', context={'vip':True})

visitor.fetch_flags()

#At this point, flags are available in the visito instance.
flag = visitor.get_flag("vip_feature", False)

#Get the value current flag value.
flag_value = flag.value()
```

This function will return a flag object containing the current value returned by Flagship and the associated\
campaign metadata. If the key is not found an empty Flag object with the default value will be returned.

| Parameter | Type                                   | Description                      |
| --------- | -------------------------------------- | -------------------------------- |
| key       | str                                    | Flag key associated to the flag. |
| default   | str \| bool \| Number \| Dict \| Array | Fallback value to us             |

### Get Flags values

#### **`def value(self, user_exposed=True)`**

Returns the current value for this flag or the default value when:

* The flag doesn't exist.
* The the current value and default value types are different.
* The flag exists from the reference variation and no value have been configured on the platform.

```python
flag = visitor.get_flag("vip_feature", False)

#Get the value current flag value.
flag_value = flag.value()

if flag_value:
  #display the feature for vip users.
```

| Parameter | Type                                   | Description                      |
| --------- | -------------------------------------- | -------------------------------- |
| key       | str                                    | Flag key associated to the flag. |
| default   | str \| bool \| Number \| Dict \| Array | Fallback value to use            |

### Expose Flags to user

Flag expositions are used to calculate visits on your campaign reporting.

By default when the `value()` method is called, the SDK considers that the visitor have seen the effets of this Flag and automatically sends a hit event to our data collection.

If you plan to use the flag value later, passing False will allow you to report flag exposition manually via the `visitor_exposed` method whenever your visitor really see the effect of the flag.

### **`def visitor_exposed(self)`**

```python
flag = visitor.get_flag("vip_feature", False)

####

flag_value = flag.value() # Visitor exposition will automatically be reported.
if flag_value:
  #display the feature for vip users.

####

flag_value = flag.value(False) # Visitor exposition won't automatically be reported.

# ...

if flag_value:
  #display the feature for vip users.
	flag.visitor_exposed() # Visitor exposition will only be reported at this point.


```

### Check if a Flag exists

Call the `exists()`method to check if a Flag exists in the Flagship SDK. This will be useful when the default value is returned from the `value()` method to know it is due to the reference variation or because the Flag do not exists.

#### **`def exists(self)`**

This function will return:

* False if the Flag do not exists in Flagship or the value type doesn't match the given default value type.
* True otherwise.

### Retrieve campaign metadata

You may need to send campaign IDs or variation IDs to a third party for reporting and/or analytics purposes. It is possible to retrieve campaigns metadata for a specific Flag.

#### **`def metadata(self)`**

This method returns a FlagMetadata object.

```python
flag = visitor.get_flag("vip_feature", False)

flag_metadata = flag.metadata()

campaign_id = flag_metadata.campaign_id
variation_group_id = flag_metadata.variation_group_id
variation_id = flag_metadata.variation_id
campaign_slug = flag_metadata.campaign_slug
campaign_type = flag_metdata.campaign_type
is_reference = flag_metadata.is_reference
```

#### **`class FlagMetadata`**

| Properties           | Type | Description                             |
| -------------------- | ---- | --------------------------------------- |
| campaign\_id         | str  | Flag campaign unique identifier.        |
| variation\_group\_id | str  | Flag variation group unique identifier. |
| variation\_id        | str  | Flag variation unique identifier.       |
| campaign\_slud       | str  | Flag campaign slug.                     |
| campaign\_type       | str  | Flag campaign type.                     |
| is\_reference        | bool | Is the Flag from variation reference.   |

***

## Send tracking hits

This section helps you track your users and learn how to build hits in order to feed campaign goals. For more information about our measurement protocol, read our [Universal Collect documentation](/server-side/concepts/universal-collect-1.md).

There are 5 types of hits: **Page**, **Screen**, **Transaction**, **Item** and **Event**.

Every hits emitted by visitors are managed by a composant called TrackingManager which gather all the visitors hits in a pool, batch them and send them at regular time intervals or when the pool max size is reached.

The TrackingManager service aims to save bandwidth traffic usage with its batch processing, but also aims to prevent any data loss as it will try to re-send hits that have failed due to network issue or save them into cache when it is necessary.

There are five different types of Hits available:

* Page
* Screen
* Transaction
* Item
* Event

Hits must all be built and sent with the `send_hit` function from the `Visitor` instance

### Send Hits

```python
from flagship.hits import Page

visitor.send_hit(Page("https://docs.developers.flagship.io/"))
```

#### **`def send_hit(self, hit)`**

Send hits as objectives in your campaign reporting.

| Parameter | Type | Description  |
| --------- | ---- | ------------ |
| hit       | Hit  | Hit to track |

### Page

This hit can be sent each time a visitor visits a web page, or a local page or in an embedded web view.

```python
from flagship.hits import Page

visitor.send_hit(Page("https://docs.developers.flagship.io/"))
```

#### **`class Page(Hit)`**

| Parameter | Type   | Description |
| --------- | ------ | ----------- |
| origin    | String | Valid URL.  |

### Screen

This hit can be sent each time a visitor arrives on an app interface.

```python
from flagship.hits import Screen

visitor.send_hit(Screen("your_screen_name"))
```

#### **`class Screen(Hit)`**

| Parameter | Type   | Description     |
| --------- | ------ | --------------- |
| origin    | String | Interface name. |

### Event

This hit can be used for

any event (e.g. Add To Cart click, newsletter subscription).

#### **`class Event(Hit)`**

```python
from flagship.hits import Event, EventCategory

visitor.send_hit(Event(EventCategory.ACTION_TRACKING, "cta_proceed_cart")
                     .with_event_label('Click basket payment')
                     .with_event_value(3))
```

| Parameters | Type          | Description                                                                                                             |
| ---------- | ------------- | ----------------------------------------------------------------------------------------------------------------------- |
| category   | EventCategory | Specifies the category of your event. NOTE: This value must be either `'ACTION_TRACKING'` or `'USER_ENGAGEMENT'`.       |
| action     | String        | Event name that will also serve as the KPI that you will have inside your reporting. [**Learn more**](doc:glossary#kpi) |

| Optional builder functions | Parameter | Type | Description                       |
| -------------------------- | --------- | ---- | --------------------------------- |
| with\_event\_label()       | label     | str  | Set the event description.        |
| with\_event\_value()       | value     | int  | Set a number value to your event. |

### Transaction

This hit can be sent when a user complete a transaction.

#### **`class Transaction(Hit)`**

```python
from flagship.hits import Transaction

visitor.send_hit(Transaction("#309830", "purchases")
                     .with_currency("EUR")
                     .with_item_count(3
                     .with_payment_method("credit_card")
                     .with_shipping_cost(14.99)
                     .with_shipping_method("Express delivery")
                     .with_taxes(240.00)
                     .with_total_revenue(1200.00)
                     .with_coupon_code("#SAVE10"))
```

| Parameters      | Type | Description                     |
| --------------- | ---- | ------------------------------- |
| transaction\_id | str  | Unique transaction ID.          |
| affiliation     | str  | Affiliation kpi name to report. |

| Optional builder functions | Parameter        | Type  | Description                                                                                                       |
| -------------------------- | ---------------- | ----- | ----------------------------------------------------------------------------------------------------------------- |
| with\_currency()           | currency         | str   | Set the local currency for all transaction currency values. Value should be a valid ISO 4217 currency code.       |
| with\_item\_count()        | item\_nb         | int   | Set the number of items purchased.                                                                                |
| with\_payment\_method()    | payment          | str   | Indicate the payment method.                                                                                      |
| with\_shipping\_cost()     | shipping         | float | Specifies the total shipping cost of the transaction.                                                             |
| with\_shipping\_method()   | shipping\_method | str   | Indicate the shipping method.                                                                                     |
| with\_taxes()              | taxes            | float | Specifies the total tax of the transaction.                                                                       |
| with\_total\_revenue()     | revenue          | float | Specifies the total revenue associated with the transaction. This value should include any shipping or tax costs. |
| with\_coupon\_code()       | coupon           | str   | Set the coupon code associated with the transaction.                                                              |

### Item

This hit can be used to link an item with a transaction. It must be sent after the corresponding transaction hit.

#### **`class Item(Hit)`**

```python
from flagship.hits import Item

visitor.send_hit(Item("#309830", "RTX4080", "#cg_rtx_40802023")
                     .with_item_category("hardware")
                     .with_item_quantity(1)
                     .with_price(1200.00))
```

| Parameters      | Type | Description                                      |
| --------------- | ---- | ------------------------------------------------ |
| transaction\_id | str  | The unique transaction ID to link with this item |
| product\_name   | str  | Name of the product.                             |
| product\_sku    | str  | Product stock keeping unit.                      |

| Optional builder functions | Parameter      | Type  | Description                                       |
| -------------------------- | -------------- | ----- | ------------------------------------------------- |
| with\_price()              | price          | float | Specifies the price for a single item / unit.     |
| with\_item\_quantity()     | item\_quantity | int   | Specifies the number of items purchased.          |
| with\_item\_category()     | category       | str   | Specifies the category which the item belongs to. |

#### Hits common builder functions

| Optional builder functions | Parameter     | Type | Description                                                                                                                                                                 |
| -------------------------- | ------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| with\_ip()                 | ip            | str  | The IP address of the user. This should be a valid IP address in IPv4 or IPv6 format. It will always be anonymized.                                                         |
| with\_resolution(          | witdh, height | int  | Set the user's device resolution. \n :param width: width in pixels. Max length 10 Bytes. Min value 0. \n :param height: height in pixels. Max length 10 Bytes. Min value 0. |
| with\_session\_number()    | number        | int  | Number of the current session for the current visitor.                                                                                                                      |
| with\_locale()             | locale        | str  | Set locale of the user's device. Max length 20 Bytes.                                                                                                                       |

## Tracking Manager configuration

TrackingManager gathers all the hits emitted by visitors in a pools before sending them into batches to our API to limit bandwidth usage. This composant is configurable at SDK `start` method, this will allow you to specify the frequency of sending batches and the max pool size so you can adapt it to your visitors and hit volumetry.

When a batch fail to be sent for example due to a network failure, all of the hits inside the failed batch will be added back into the pool for future iteration.

To prevent any data loss, configure a custom cache implementation, see [CacheManager](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#manage-sdk-cache), in order for the `TrackingManager` to be able to cache the remaining Hits in the pool when your app close, and load them when it needs to try to send them again. The `CachingStrategy` will help you to specify at which frequency the cache will be updated.

```python
from flagship import Flagship
from flagship.config import Bucketing
from flagship.tracking_manager import TrackingManagerConfig, CacheStrategy

Flagship.start('_YOUR_ENV_ID_', '_YOUR_API_KEY_', DecisionApi(
                                                		tracking_manager_config=TrackingManagerConfig,
                                                    	max_pool_size=10,
                                                    	time_interval=2000,
																											cache_strategy=CacheStrategy.PERIODIC_CACHING))
```

| Kwarg parameter | Type          | Default value                              | Description                                                                                                                                                                                         |
| --------------- | ------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| max\_pool\_size | int           | Default is 20                              | Define the minimum number of hits the pool must reach to automatically batch all hits in the pool and send it \n \n**Note**: \n- Having a very large max\_pool\_size can lead to performance issues |
| time\_interval  | int           | 10000 ms                                   | Define a regular interval in milliseconds to trigger batch processing \n \n**Note**: \n- The process will batch all hits from the pool whether max\_pool\_size is reached or not.                   |
| cache\_strategy | CacheStrategy | CONTINUOUS\_CACHING \| \nPERIODIC\_CACHING | Define the strategy that will be used for hit caching. See \n[CacheStrategy](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#hits-caching-strategy)     |

### Hits caching strategy

The `CacheStrategy` enum class specifies the hits caching strategy to adopt into the TrackingManager and relies on the `HitCacheImplementation` class that must be implemented in the CacheManager. Depending on the strategy the `TrackingManager` will request the `CacheManager` to CACHE, LOOK-UP or FLUSH hits from the linked database.

There are two available values for the `CacheStrategy`:

| Key                 | Description                                                                                                                                                                                                                                                                                                              |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| CONTINUOUS\_CACHING | Hits will be continuously cached and flushed from the database. The database linked to the `HitCacheImplementation` class implemented in the provided `CacheManager` will be required each time time a hit is added or flushed from the `TrackingManager` pool.                                                          |
| PERIODIC\_CACHING   | Hits will be cached and flushed from the database periodically. The database linked to the `HitCacheImplementation` class implemented in the provided `CacheManager` will be required to cache/look-up/flush hits at regular time intervals. The time intervals relies on the `TrackingManager` 'time\_interval' option. |

***

## Manage SDK Cache

At some points the Flagship SDK will require to cache and retrieve some information about visitors and hits.

Cached data will be used to:

* Prevent re-allocation in bucketing mode if you have changed your traffic allocation in bucketing mode.
* Handle Hits that failed to be sent due to network failure.
* Be compatible with some features in Bucketing mode, like Dynamic allocation and Progressives Roll-out.

The Python SDK provides a way for you to customize where it will cache the needed data tanks to an interface to implement. You might want to pass your custom cache interface implementation to save and load data from an existing Redis or Memcached service.

{% hint style="info" %}
📘 Sqlite implementation

The SDK already embeds a predefined Sqlite implementation to cache data locally but it is will only be suitable for services that handle one visitor at a time like python apps, scripts, IOT.
{% endhint %}

### Customize cache manager

Set your custom cache implementation in the `start` method. See [configuration](#configure-your-python-sdk) :

```python
from flagship import Flagship
from flagship.config import DecisionApi
from flagship.cache_manager import CacheManager, VisitorCacheImplementation, HitCacheImplementation

class CustomCacheManager(CacheManager, VisitorCacheImplementation, HitCacheImplementation):
        def __init__(self):
            super().__init__()

        def open_database(self, env_id):
            #Create or open your database
            pass

        def close_database(self):
            #close your database
            pass

        async def cache_visitor(self, visitor_id, data):
            #Upsert visitor information corresponding to the given id into your database here.
            pass

        async def lookup_visitor(self, visitor_id):
            #Load and return visitor information corresponding to the given id from your database here.
            pass

        async def flush_visitor(self, visitor_id):
            #Delete visitor information corresponding to the given id from your database here.
            pass

        def cache_hits(self, hits):
            #Cache the given hits into your database here.
            pass
        async def lookup_hits(self):
            #Load and return all the cached hits from your database here.
            pass

        def flush_hits(self, hits_ids):
            #Delete hits corresponding to the given id from your database here.
            pass

        def flush_all_hits(self):
            #Delete all the hits cached hits from your database here.
            pass
          
Flagship.start(env_id, api_key, DecisionApi(cache_manager=CustomCacheManager())
```

There are two cache interfaces to implement:

### Visitor cache interface

The`VisitorCacheImplementation` class aims to provide an interface between the Flagship SDK and an existing database in order for the SDK to store visitors data. It defines the methods that will be called to handle the cache mechanism.

**`VisitorCacheImplementation`**

#### Cache visitor

This method is called when the Flagship SDK needs to save visitor's data into cache.

**`async def cache_visitor(self, visitor_id: str, data: dict)`**

| Parameter   | Type | Description                                          |
| ----------- | ---- | ---------------------------------------------------- |
| visitor\_id | str  | Identifier of the visitor whose data must be cached. |
| data        | dict | Visitor's data to be cached.                         |

#### Lookup visitor

This method is called when the Flagship SDK needs to load visitor's data from cache.

**`async def lookup_visitor(self, visitor_id: str)`**

| Parameter   | Type | Description                                           |
| ----------- | ---- | ----------------------------------------------------- |
| visitor\_id | str  | Identifier of the visitor whose cache must be loaded. |

#### Flush visitor

This method is called when the Flagship SDK needs to flush visitor's data from cache.

**`async def flush_visitor(self, visitor_id: str)`**

| Parameter   | Type | Description                                            |
| ----------- | ---- | ------------------------------------------------------ |
| visitor\_id | str  | Identifier of the visitor whose cache must be flushed. |

### Hit cache interface

The `HitCacheImplementation` class aims to provide an interface between the Flagship SDK and an existing database in order to store hits data in case of error or network failure. It defines the methods that will be called by the SDK to handle the cache mechanism depending on the strategy.

**`HitCacheImplementation`**

#### Cache hits

This method is called when the Flagship SDK needs to save visitors hits into cache.

**`def cache_hits(self, hits)`**

| Parameter | Type | Description                                          |
| --------- | ---- | ---------------------------------------------------- |
| hits      | dict | Dictionary of hits that need to be saved into cache. |

#### Lookup hits

This method is called when the Flagship SDK needs to load visitors hits from the cache.

**`async def lookup_hits(self)`**

#### Flush hits

**`def flush_hits(self, hits_ids)`**

| Parameter | Type | Description                                  |
| --------- | ---- | -------------------------------------------- |
| hits\_ids | dict | Hits ids that need to be flushed from cache. |

#### Flush all hits

**`def flush_all_hits(self)`**

This method is called when the Flagship SDK needs to flush all the hits from cache.

***

## Keep visitors experience continuity

Dealing with anonymous and logged-in users, experience continuity allows you to maintain consistency between sessions and devices. See [Experience continuity](/server-side/concepts/experience-continuity.md) concept for more details.

{% hint style="warning" %}
🚧 Enable experience continuity feature

The use of this feature requires having the option enabled in your Flagship account beforehand. Select the desired environment and go to /settings/environment-settings and enable the "Experience Continuity" option.
{% endhint %}

### Authenticate a visitor

There are 2 ways to authenticate a visitor and let the SDK knows that your visitor is authenticated:

1. Set the `authenticated` to **True** when creating a new visitor. See [create new visitor](#create-new-visitors).
2. Use `authenticate()` function of `Visitor` instance.

**`def authenticate(self, visitor_id)`**

This function will indicate to the SDK that the anonymous visitor is now authenticated, this will insure to keep the same experience.

```python
visitor.authenticate("visitor_unique_id")
```

| Parameter   | Type | Description                                      |
| ----------- | ---- | ------------------------------------------------ |
| visitor\_id | str  | Current authenticated visitor unique identifier. |

{% hint style="warning" %}
🚧 Update visitor flags

Because the visitor have been now identified, it is required to call the `fetch_flags()`function of the visitor instance so his flags will be updated accordingly. See [fetching flags](#fetch-flags).
{% endhint %}

### Un-Authenticate a visitor

**`def unauthenticate(self)`**

```python
visitor.unauthenticate()
```

This function will indicate to the SDK the authenticated visitor is now un-authenticated and back to anonymous.

{% hint style="warning" %}
🚧 Update visitor flags

Because the visitor have been now identified, it is required to call the `fetch_flags()`function of the visitor instance so his flags will be updated accordingly. See [fetching flags](https://github.com/flagship-io/Gitbook/blob/main/SDKs/python-sdk/python-reference/README.md#fetching-flags).
{% endhint %}

***

## Customize the logs of the SDK

The SDK provides a way for you to intercept and/or customize the logs emitted. It is possible to pass your own implementation of the `LogManager` class in the configuration.

The `log_level` option of the `start` method will filter the emitted logs.

```python
from flagship import Flagship, LogLevel
from flagship.config import DecisionApi
from flagship.decision_mode import DecisionMode
from flagship.log_manager import LogManager, FlagshipLogManager

class CustomLogManager(LogManager):

        def log(self, tag, level, message):
            pass

        def exception(self, exception, traceback):
            pass

 Flagship.start("_env_id_", "_api_key_", DecisionApi(
        timeout=3000,
        log_level=LogLevel.DEBUG,
        status_listener=CustomStatusListener(),
        polling_interval=2000,
        log_manager=CustomLogManager()
    ))
```

***

## Get the SDK status

The SDK can have different status states.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.abtasty.com/server-side/sdks/python/python-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
