|
| 1 | +# Migrate to the Wingify Python FME SDK |
| 2 | + |
| 3 | +This guide explains how to adopt the **Wingify** public API on the Python FME SDK. Existing **VWO** integrations (`vwo-fme-python-sdk`) continue to work without changes. |
| 4 | + |
| 5 | +For installation, requirements, and advanced configuration (storage, logger, gateway, proxy, polling, and more), see [README.md](README.md). |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Overview |
| 10 | + |
| 11 | +The FME SDK is published as **two PyPI packages** built from the **same codebase** at the same version: |
| 12 | + |
| 13 | +| PyPI package | Import | Public types | |
| 14 | +| --- | --- | --- | |
| 15 | +| [`wingify-fme-python-sdk`](https://pypi.org/project/wingify-fme-python-sdk/) | `import wingify` | `WingifyOptionsModel`, `WingifyClient`, … | |
| 16 | +| [`vwo-fme-python-sdk`](https://pypi.org/project/vwo-fme-python-sdk/) | `import vwo` | `VWOOptionsModel`, `VWOClient`, … (legacy) | |
| 17 | + |
| 18 | +Pick **one** package for your app — do **not** install both `vwo-fme-python-sdk` and `wingify-fme-python-sdk` in the same environment. |
| 19 | + |
| 20 | +New integrations should use the **Wingify** package and types. When you install and initialize through `wingify-fme-python-sdk`, the SDK uses Wingify edge/collect endpoints and Wingify-branded logging (see [Runtime behavior](#runtime-behavior-wingify-build) below). |
| 21 | + |
| 22 | +--- |
| 23 | + |
| 24 | +## Wingify API — implementation guide |
| 25 | + |
| 26 | +Use PyPI package `wingify-fme-python-sdk`. Public types use the `Wingify*` prefix. |
| 27 | + |
| 28 | +Legacy `VWO*` types on `vwo-fme-python-sdk` remain supported; they are thin aliases over the same core implementation. |
| 29 | + |
| 30 | +### Implementation steps |
| 31 | + |
| 32 | +1. **Add the dependency** — use only the Wingify coordinate (same semver you use on VWO today): |
| 33 | + |
| 34 | + ```bash |
| 35 | + pip install wingify-fme-python-sdk |
| 36 | + ``` |
| 37 | + |
| 38 | +2. **Initialize** — call `init()` with `account_id` and `sdk_key`. Returns a `WingifyClient`. |
| 39 | + |
| 40 | +3. **Build user context** — pass a plain dict with at least `id` (string). Optional: `custom_variables`, `user_agent`, `ip_address`, `bucketingSeed`, etc. See [README.md](README.md). |
| 41 | + |
| 42 | +4. **Evaluate flags** — `client.get_flag(feature_key, context)`. |
| 43 | + |
| 44 | +5. **Track and attribute** — `track_event`, `set_attribute`, and `set_alias` on the initialized client. |
| 45 | + |
| 46 | +### Python |
| 47 | + |
| 48 | +```python |
| 49 | +from wingify import init |
| 50 | + |
| 51 | +client = init({ |
| 52 | + 'account_id': '123456', |
| 53 | + 'sdk_key': '32-alpha-numeric-sdk-key', |
| 54 | + 'logger': {'level': 'DEBUG'}, |
| 55 | +}) |
| 56 | + |
| 57 | +context = {'id': 'unique_user_id', 'custom_variables': {'plan': 'pro'}} |
| 58 | + |
| 59 | +flag = client.get_flag('feature_key', context) |
| 60 | + |
| 61 | +if flag.is_enabled(): |
| 62 | + variable = flag.get_variable('feature_variable', 'default-value') |
| 63 | + print('Variable:', variable) |
| 64 | + |
| 65 | +client.track_event('event_name', context, {'cartValue': 10}) |
| 66 | +client.set_attribute('attribute_key', 'attribute_value', context) |
| 67 | +client.set_alias(context, 'alias_id') |
| 68 | +``` |
| 69 | + |
| 70 | +### Type hints (Wingify package) |
| 71 | + |
| 72 | +```python |
| 73 | +from wingify import init, WingifyClient, WingifyOptionsModel |
| 74 | + |
| 75 | +options: WingifyOptionsModel = WingifyOptionsModel({ |
| 76 | + 'accountId': '123456', |
| 77 | + 'sdkKey': '32-alpha-numeric-sdk-key', |
| 78 | +}) |
| 79 | + |
| 80 | +client: WingifyClient = init({ |
| 81 | + 'account_id': '123456', |
| 82 | + 'sdk_key': '32-alpha-numeric-sdk-key', |
| 83 | +}) |
| 84 | +``` |
| 85 | + |
| 86 | +For the legacy VWO package, substitute `VWOClient` and `VWOOptionsModel` — behavior is the same. |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## Public API mapping |
| 91 | + |
| 92 | +| Legacy (VWO package) | Wingify package | |
| 93 | +| --- | --- | |
| 94 | +| `init` | `init` | |
| 95 | +| `getUUID` | `getUUID` | |
| 96 | +| `VWOOptionsModel` | `WingifyOptionsModel` | |
| 97 | +| `VWOClient` | `WingifyClient` | |
| 98 | +| `vwoBuilder` on options | `wingifyBuilder` (preferred); `vwoBuilder` still accepted | |
| 99 | +| `StorageConnector`, `LogLevelEnum` | Same export names | |
| 100 | + |
| 101 | +### Options that stay VWO-named (platform compatibility) |
| 102 | + |
| 103 | +| Option / field | Notes | |
| 104 | +| --- | --- | |
| 105 | +| `_vwo_meta` | Still supported; use for SDK metadata when needed | |
| 106 | +| Context `_vwo` | Still supported for UA / device hints; `_wingify` also accepted | |
| 107 | +| Event / payload keys (e.g. `_vwo_meta` in network payloads) | Unchanged for server compatibility | |
| 108 | +| `vwoBuilder` | Alias of `wingifyBuilder` on init options | |
| 109 | +| Local storage key | `vwo_fme_settings` for both brands | |
| 110 | + |
| 111 | +--- |
| 112 | + |
| 113 | +## Legacy VWO API |
| 114 | + |
| 115 | +The following remain available for existing apps on **`vwo-fme-python-sdk`**: |
| 116 | + |
| 117 | +- `import vwo` with `init`, `getUUID` |
| 118 | +- `VWOClient`, `VWOBuilder`, `VWOOptionsModel` |
| 119 | +- `vwoBuilder`, `StorageConnector`, logger hooks |
| 120 | +- VWO build-time hosts and `VWO-SDK` log prefix |
| 121 | + |
| 122 | +No breaking change is required to stay on the VWO package. |
| 123 | + |
| 124 | +--- |
| 125 | + |
| 126 | +## Runtime behavior (Wingify build) |
| 127 | + |
| 128 | +When you install and run the **Wingify** PyPI build (not `vwo-fme-python-sdk`): |
| 129 | + |
| 130 | +| Area | Wingify build | VWO build (legacy package) | |
| 131 | +| --- | --- | --- | |
| 132 | +| Settings / pull / location | `edge.wingify.net` | `dev.visualwebsiteoptimizer.com` | |
| 133 | +| Events / batch | `collect.wingify.net` | Same host as settings (single host) | |
| 134 | +| Log prefix | `Wingify-SDK` | `VWO-SDK` | |
| 135 | +| Log message branding | Wingify where templated | VWO | |
| 136 | +| PyPI `name` in metadata | `wingify-fme-python-sdk` | `vwo-fme-python-sdk` | |
| 137 | + |
| 138 | +With **`proxy_url`**, all requests go to your proxy host. Without `proxy_url`, the SDK selects hosts automatically per build brand. |
| 139 | + |
| 140 | +Event and API payload field names (for example `_vwo_meta`, `vwo_*` event names) are **unchanged** for compatibility with the FME platform. |
| 141 | + |
| 142 | +--- |
| 143 | + |
| 144 | +## Migrating from `vwo-fme-python-sdk` to `wingify-fme-python-sdk` |
| 145 | + |
| 146 | +1. In `requirements.txt`, replace the dependency: |
| 147 | + |
| 148 | + ```diff |
| 149 | + - vwo-fme-python-sdk==1.50.0 |
| 150 | + + wingify-fme-python-sdk==1.50.0 |
| 151 | + ``` |
| 152 | + |
| 153 | +2. Update imports: |
| 154 | + |
| 155 | + ```diff |
| 156 | + - from vwo import init |
| 157 | + + from wingify import init |
| 158 | + ``` |
| 159 | + |
| 160 | +3. Rename types: `VWOClient` → `WingifyClient`, `VWOOptionsModel` → `WingifyOptionsModel`. |
| 161 | + |
| 162 | +4. If you pass a custom builder, prefer `wingifyBuilder` instead of `vwoBuilder` (either still works). |
| 163 | + |
| 164 | +5. Reinstall and run your existing tests — flag evaluation, tracking, and attributes behave the same; only package name, exported type names, default hosts, and log branding change. |
| 165 | + |
| 166 | +### What you do **not** need to change |
| 167 | + |
| 168 | +- `account_id`, `sdk_key`, feature keys, event names |
| 169 | +- User context shape (`{'id': '...'}` and optional fields) |
| 170 | +- Method signatures on the client (`get_flag`, `track_event`, etc.) |
| 171 | +- Server-side campaign / settings JSON |
| 172 | +- `_vwo` / `_vwo_meta` in context or payloads when you already send them |
| 173 | + |
| 174 | +--- |
| 175 | + |
| 176 | +## Architecture note |
| 177 | + |
| 178 | +The SDK follows a **Single Repo Two Pacakge Approach**: |
| 179 | + |
| 180 | +| Package | Role | |
| 181 | +| --- | --- | |
| 182 | +| `wingify/` | **Core** — `api/`, `constants/`, `enums/`, `services/`, `utils/`, `packages/`, `wingify_client.py`, … | |
| 183 | +| `vwo/` | **Legacy facade only** (~10 files) — `init`, `VWOClient`, `VWOBuilder`, `VWOOptionsModel`, `StorageConnector`, `LogLevelEnum`, etc. | |
| 184 | + |
| 185 | +Both PyPI wheels ship `wingify` (core) and `vwo` (facade). Existing apps use `import vwo`; new apps use `import wingify`. Brand-specific hosts, SDK name, and log prefix are selected at **runtime** via `is_via_vwo` (`vwo.init()` sets it to `true`; `wingify.init()` defaults to `false`). PyPI wheel metadata still differs per `SDK_BRAND` at build time. |
| 186 | + |
| 187 | +--- |
| 188 | + |
| 189 | +## Related documents |
| 190 | + |
| 191 | +| Document | Content | |
| 192 | +| --- | --- | |
| 193 | +| [README.md](README.md) | Installation, requirements, configuration | |
| 194 | +| [CHANGELOG.md](CHANGELOG.md) | Version history and rebranding notes | |
0 commit comments