1755399261
2025-08-16 11:09:00
OptMizelyには、カスタムオーディエンス/訪問者グループの作成を可能にする強力なパーソナライズエンジンがあります。ただし、1つの制限が付いています。非同期操作はサポートしていません。以下のソリューションは、Optimizelyで非同期操作を実行できないシナリオで機能します。
これが実際のユースケースと、私たちがそれをどのように回避したかです。
ユーザーエクスペリエンスのパーソナライズは、訪問者がどこから来たのかを知ることから始まります。軽量のアプローチの1つは、ユーザーのIPアドレスをに変換することです 郵便番号 ユーザーの場所(州の実行など)に応じて、ユーザーのエクスペリエンスをパーソナライズします。 Optimizely CMS 12(ASP.NET Core 8で実行)では、これを行う方法について ミドルウェア。
なぜミドルウェア?
訪問者グループ 重要な制限があります:訪問者グループの基準は同期して実行する必要があります。これは、多くのIPからZIPサービスを除外する外部サービスにスレッドブロック呼び出しを引き起こすことなく、訪問者グループを評価するときに、外部APIを安全に呼び出したり、非同期検索を待つことができないことを意味します。一方、ASP.NETコアミドルウェアは、すべての要求(フィルタリングできる)に対して実行され、非同期操作を完全にサポートします。概説されているように、asynchelper.runsync()を使用します ここ スケーラブルなソリューションではなく、アプリケーションにスレッドプールの飢vとデッドロックを引き起こす可能性があります。これにより、地理的、ロギング、認証、リクエストの濃縮などの懸念に理想的な場所になります。パイプラインの開始時に郵便番号を1回解決することにより、コントローラー、ブロックコントローラー、またはビューの複製の検索を同時に避け、外部サービスへの呼び出しのブロックを避けます。
ステップ1:リクエストスコープコンテナを作成します
Scopedクラスを使用して、DIから簡単にアクセスできるように、解決された郵便番号を保存します。
public sealed class GeoContext
{
public string? ZipCode { get; set; }
}
ステップ2:IP→zipリゾルバーを定義します
これは、IPアドレスを郵便番号に変えるサービスです。サードパーティAPI、Maxmind、または独自のデータソースを使用できます。
public interface IZipFromIpResolver
{
Task GetZipFromIpAsync(string ip, CancellationToken ct = default);
}
ステップ3:ミドルウェアを実装します
ミドルウェアはクライアントIPを取得し、リゾルバーを呼び出し、結果をGeoContextに保存します
public sealed class GeoZipMiddleware
{
private readonly RequestDelegate _next;
public GeoZipMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext context, GeoContext geo, IZipFromIpResolver resolver)
{
// Filter out any paths to avoid calling the service on these requests
var path = httpContext.Request.Path.Value ?? "";
if (!path.StartsWith("/assets", StringComparison.OrdinalIgnoreCase) &&
!path.StartsWith("/static", StringComparison.OrdinalIgnoreCase) &&
!path.StartsWith("/api/custom", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/globalassets", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/.well-known", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/siteassets", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/Errors", StringComparison.OrdinalIgnoreCase) &&
!path.Contains("/contentassets", StringComparison.OrdinalIgnoreCase)) // Optimizely blobs
{
var ip = context.Connection.RemoteIpAddress?.ToString();
if (!string.IsNullOrWhiteSpace(ip))
{
try
{
// Call your GeoLocation Service
geo.ZipCode = await resolver.GetZipFromIpAsync(ip);
// You can also save it within the httpContext
httpContext.Items["ZipCode"] = geo.ZipCode;
}
catch
{
// log if needed; don’t block the request
}
}
}
await _next(context);
}
}
ステップ4:サービスとミドルウェアを登録します
プログラムを更新します
var builder = WebApplication.CreateBuilder(args);
// Add request-scoped container
builder.Services.AddScoped();
// Add resolver implementation
// builder.Services.AddSingleton();
builder.Services.AddHttpContextAccessor();
var app = builder.Build();
// Use middleware early in the pipeline
app.UseMiddleware();
app.UseRouting();
app.UseAuthorization();
app.MapContent();
app.Run();
ステップ5:コントローラー、ブロック、またはビューで使用します
GeoContextはスコープされているため、どこにでも注入できます。 httpcontext.itemsを使用して値を取得することもできます(ミドルウェアで設定)
public override bool IsMatch(IPrincipal principal, HttpContext httpContext)
{
var zipCode = httpContext.Items["ZipCode"];
// do something with it
return true;
}
メモとベストプラクティス
-
キャッシング:IPからZIPの検索は高価になる可能性があります。 isynchronizedObjectCacheまたは分散キャッシュを使用して、API呼び出しを削減します。
-
プライバシー:IPおよびロケーションデータを個人情報(GDPR/CCPA)として扱います。明確なユースケースがない限り、持続を避けてください。
-
パフォーマンス:静的資産やその他のURLリクエストをミドルウェア内で速度でスキップすることを検討してください。
まとめます
Optimizely CMS 12でASP.NETコアミドルウェアを活用することにより、各リクエストをジオロケーションまたはその他のデータで簡単に充実させることができます。これは強力であり、アプリケーションからのブロックコールを削除することにより、Webサイトのパフォーマンスを大幅に改善できます。
2025年8月16日
#Optimizelyの非同期制限を回避する訪問者Gr