Opti.ODP 1.0.2-beta

This is a prerelease version of Opti.ODP.
The owner has unlisted this package. This could mean that the package is deprecated, has security vulnerabilities or shouldn't be used anymore.
dotnet add package Opti.ODP --version 1.0.2-beta
                    
NuGet\Install-Package Opti.ODP -Version 1.0.2-beta
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Opti.ODP" Version="1.0.2-beta" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Opti.ODP" Version="1.0.2-beta" />
                    
Directory.Packages.props
<PackageReference Include="Opti.ODP" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Opti.ODP --version 1.0.2-beta
                    
#r "nuget: Opti.ODP, 1.0.2-beta"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Opti.ODP@1.0.2-beta
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Opti.ODP&version=1.0.2-beta&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Opti.ODP&version=1.0.2-beta&prerelease
                    
Install as a Cake Tool

Opti.ODP

Optimizely Data Platform (ODP) integration for Optimizely CMS 12. Provides visitor group criteria based on real-time ODP audiences with scheduled audience caching, encrypted cookie-based tracking, and a diagnostic API.

Features

  • Visitor Group Criterion — Select ODP audiences from a dropdown in the CMS admin UI
  • Scheduled Audience Sync — Automatically caches all ODP audiences every hour via a scheduled job
  • Real-time Audience Matching — Fetches user audience membership from ODP on every page load via middleware
  • Encrypted Cookie Tracking — Stores matched audiences in an encrypted usr_seg cookie (configurable)
  • Resilient Caching — Cache persists for 24 hours and is preserved if the sync job fails
  • Load-balanced Support — Uses ISynchronizedObjectInstanceCache for multi-server environments
  • Fallback — Criterion reads from cookie first; if missing, fetches from ODP API and sets the cookie

Installation

1. Install NuGet Package

dotnet add package Opti.ODP

Or via Package Manager Console: Install-Package Opti.ODP

2. Configure in Startup.cs

public void ConfigureServices(IServiceCollection services) { // Register ODP services (before AddCms) services.AddOptimizelyOdp(Configuration); services.AddCms(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseAuthentication(); app.UseAuthorization(); // ODP middleware — fetches user audiences on every page load app.UseMiddleware<Optimizely.ODP.Middleware.OdpSegmentMiddleware>();

app.UseRouting(); app.UseEndpoints(endpoints ⇒ { endpoints.MapControllers(); endpoints.MapContent(); }); }

3. Add Configuration (appsettings.json)

{ "Optimizely": { "OdpSettings": { "PrivateApiKey": "your-private-api-key-here", "ApiHost": "https://api.zaius.com", "SegmentCookieName": "usr_seg", "SegmentCookieExpirationMinutes": 10, "SegmentCacheExpirationMinutes": 1440, "EncryptCookie": true } } }

Where to find your API key:

  1. Log in to your ODP account
  2. Navigate to Settings → APIs & Credentials
  3. Copy your Private API Key

4. Run the Audience Sync Job

  1. Go to Admin → Scheduled Jobs
  2. Find ODP Audience Sync
  3. Click Start Manually to populate the cache for the first time
  4. The job runs automatically every hour (configurable in Admin UI)

5. Restart Your Application

After installation and configuration, restart your application.

How It Works

Page Load │ ├─ Middleware (runs first on every page load) │ ├─ Reads vuid cookie │ ├─ Parses GUID (removes hyphens and timestamp) │ ├─ Calls ODP GraphQL API with cached audience subset │ └─ Writes/refreshes encrypted usr_seg cookie │ ├─ Visitor Group Criterion (runs during page render) │ ├─ Reads usr_seg cookie (fast, no API call) │ ├─ Decrypts and checks audience membership │ └─ If cookie missing → falls back to ODP API call │ └─ Response sent with fresh usr_seg cookie

Usage

Creating Visitor Groups

  1. In Optimizely CMS, go to Admin → Visitor Groups
  2. Create a new visitor group or edit an existing one
  3. Click Add Criterion
  4. Select Optimizely ODP → ODP Audience
  5. Choose an ODP audience from the dropdown
  6. Save the visitor group

Programmatic Usage

public class MyController : Controller { private readonly IOdpService _odpService; public MyController(IOdpService odpService) { _odpService = odpService; }

public async Task<IActionResult> Index() { var userId = Request.Cookies["vuid"] ?? User.Identity?.Name;

// Get all matched audiences for a user (calls ODP API)
var audiences = await _odpService.GetCustomerSegmentsAsync(userId);

// Check if user is in a specific audience
var isVip = await _odpService.IsInSegmentAsync(userId, "VIP Customers");

// Read audiences from cookie only (no API call)
var cookieAudiences = _odpService.GetAudiencesFromCookie(HttpContext);

// Get customer fields
var fields = await _odpService.GetCustomerFieldsAsync(userId, new[] { "email", "loyalty_tier" });

// Post an event to ODP
await _odpService.PostEventAsync("page_view", "viewed", new Dictionary<string, object>
{
    ["page_name"] = "Home",
    ["category"] = "Landing"
});

return View();

} }

Configuration Options

Property Default Description
PrivateApiKey (required) Your ODP Private API Key
ApiHost https://api.zaius.com ODP API endpoint
SegmentCookieName usr_seg Cookie name for storing user audiences
SegmentCookieExpirationMinutes 10 Cookie expiration in minutes
SegmentCacheExpirationMinutes 1440 Cache expiration in minutes (default: 24 hours)
EncryptCookie true Encrypt cookie using ASP.NET Data Protection

When EncryptCookie is true (default), the usr_seg cookie value is encrypted using ASP.NET Data Protection (AES-256).

EncryptCookie Cookie value Readable?
true CfDJ8N...base64... No — encrypted
false ["VIP Customers","Cart Abandoners"] Yes — plain JSON

The package handles both formats seamlessly. You can switch between encrypted and plain at any time without losing existing cookies.

Protection How
Encryption ASP.NET Data Protection API (AES-256-CBC)
Tamper-proof HMAC signature — modification invalidates the cookie
HttpOnly Not accessible via JavaScript
Secure Only sent over HTTPS
SameSite=Lax CSRF protection

Scheduled Job

Setting Value
Name ODP Audience Sync
Default interval Every 60 minutes
Initial delay 1 minute after startup
Cache TTL 24 hours
Failure behaviour Preserves existing cache
Configurable Yes, via Admin → Scheduled Jobs

The job output displays all synced audience names as a comma-separated list.

API Reference

IOdpService

Method Description
GetCustomerSegmentsAsync(string userId) Fetch audiences from ODP API and refresh cookie
GetAudiencesFromCookie(HttpContext httpContext) Read audiences from cookie only (no API call)
GetAllSegmentsAsync() Fetch all audiences from ODP API
GetAvailableSegmentsAsync() Get audience names (from cache or API)
GetCachedSegmentKeysAsync() Get audience names from cache only
RefreshSegmentCacheAsync() Refresh the audience cache from ODP API
GetCustomerFieldsAsync(string userId, IEnumerable<string> fields) Retrieve customer data fields
PostEventAsync(string type, string action, IDictionary<string, object> data) Send events to ODP
IsInSegmentAsync(string userId, string segmentName) Check if user is in a specific audience

Troubleshooting

  1. Run the ODP Audience Sync job manually from Admin → Scheduled Jobs
  2. Verify API credentials in appsettings.json
  3. Ensure audiences exist in your ODP account
  4. Check application logs for ODP Audience Sync messages
  1. Ensure the middleware is registered: app.UseMiddleware<OdpSegmentMiddleware>()
  2. Verify the ODP JavaScript snippet is on your site (sets the vuid cookie)
  3. Check that HTTPS is enabled (cookie has Secure flag)
  4. Check logs for ODP Middleware: Parsed userId messages
  5. Use the diagnostic endpoint: GET /api/odp/my-audiences

User not matching any audiences

  1. Verify the vuid cookie exists in the browser
  2. Use the diagnostic endpoint: GET /api/odp/check-user/{vuid}
  3. Check application logs for ODP GraphQL Response

Cache is empty after restart

The cache is in-memory and will be empty after an application restart. The scheduled job runs 1 minute after startup to repopulate it. You can also run it manually from Admin → Scheduled Jobs.

The ODP JavaScript snippet sets a vuid cookie in this format:

vuid=%7Cauth0|604dc23ae94c1f001c70a8f7|f79e9eca-6920-4cfb-9b5f-622480656f6c

The package automatically:

  1. URL-decodes (%7C → |)
  2. Splits on | and takes the GUID
  3. Removes hyphens → 56a87f1b25b44324aff3b5c9fa12ad1d

This is the format ODP expects for the vuid identifier.

Performance

At 200K+ requests/day:

Operation Cost When
Cookie read + decrypt ~0.02ms Every request
ODP API call 50-200ms Once per page load (middleware)
Criterion evaluation ~0.02ms Reads cookie only

The criterion reads from the cookie during page render. API calls only happen in the middleware before the page renders, or as a fallback if the cookie is missing.

License

MIT License

Support

https://github.com/bodhibasu/Optimizely.ODP

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated

v1.0.2-beta:
- Visitor group criterion with ODP audience dropdown
- Scheduled job (ODP Audience Sync) to cache all audiences hourly
- Real-time audience matching via middleware on every page load
- Encrypted cookie (usr_seg) using ASP.NET Data Protection (configurable)
- Cookie-first evaluation with ODP API fallback
- Diagnostic API endpoints for troubleshooting (admin-only)
- vuid cookie parsing (URL-decode, strip hyphens, remove timestamp)
- GraphQL subset query for per-user audience membership
- Resilient caching: preserves cache on job failure
- Load-balanced support via ISynchronizedObjectInstanceCache