vTilt
Why vTiltHow It WorksFeaturesFAQDocs
Docs / .NET / C#
Quick startEvent forwarding
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceGoogle Ads
Client setup
CursorClaude DesktopVS CodeCodex
Realtime
Debug ViewRealtime Dashboard
Integration guides
Frontend frameworks
Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus
Backend frameworks
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails
Backend languages
PythonPHPRubyElixirGoJava.NET / C#Rust
Stack guides
Vue + PHP
SDK
Browser SDK
InstallScript bundlesEvent trackingAutocaptureIdentify & aliasWeb VitalsSession recordingChat widgetFeature readinessRemote configurationReverse proxyDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdown

Documentation

vTilt
Quick startEvent forwarding

MCP server

Realtime

Debug ViewRealtime Dashboard

Integration guides

PythonPHPRubyElixirGoJava.NET / C#Rust

SDK

DocsIntegration guides.NET / C#

.NET / C#

Send vTilt events from .NET code (ASP.NET Core, console apps, Azure Functions) by POSTing to the ingest API.

There's no native .NET SDK yet, but vTilt's wire format is a plain JSON POST so any C# code can emit events. The pattern below uses HttpClient + System.Text.Json; the same shape works inside ASP.NET Core, ASP.NET MVC, Blazor Server, Azure Functions, console apps, and worker services.

#1. Configure

# .env / appsettings.json
VTILT_TOKEN=YOUR_PROJECT_TOKEN
VTILT_HOST=https://www.vtilt.com
text

#2. Capture client

A typed HttpClient exposed through IHttpClientFactory. Captures are awaited inside Task.Run so handlers don't block on network IO.

// Vtilt/VtiltClient.cs
using System.Net.Http.Json;

public sealed class VtiltClient
{
    private readonly HttpClient _http;
    private readonly string _token;
    private readonly ILogger<VtiltClient> _log;

    public VtiltClient(HttpClient http, IConfiguration config, ILogger<VtiltClient> log)
    {
        _http = http;
        _http.BaseAddress = new Uri(config["VTILT_HOST"] ?? "https://www.vtilt.com");
        _http.Timeout = TimeSpan.FromSeconds(2);
        _token = config["VTILT_TOKEN"] ?? throw new InvalidOperationException("VTILT_TOKEN missing");
        _log = log;
    }

    public void Capture(string distinctId, string @event, IDictionary<string, object>? properties = null)
    {
        var payload = new
        {
            api_key = _token,
            @event = @event,
            distinct_id = distinctId,
            properties = properties ?? new Dictionary<string, object>(),
        };

        _ = Task.Run(async () =>
        {
            try
            {
                await _http.PostAsJsonAsync("/api/e", payload);
            }
            catch (Exception ex)
            {
                _log.LogWarning(ex, "vtilt capture failed");
            }
        });
    }

    public void Identify(string distinctId, IDictionary<string, object> properties)
    {
        Capture(distinctId, "$identify", new Dictionary<string, object> { ["$set"] = properties });
    }
}
csharp
// Program.cs
builder.Services.AddHttpClient<VtiltClient>();
csharp

#3. Capture events

public class CheckoutController : ControllerBase
{
    private readonly VtiltClient _vtilt;
    public CheckoutController(VtiltClient vtilt) => _vtilt = vtilt;

    [HttpPost("/checkout")]
    public IActionResult Complete([FromBody] CheckoutRequest req)
    {
        _vtilt.Identify(req.UserId, new Dictionary<string, object> { ["plan"] = "pro" });

        _vtilt.Capture(req.UserId, "purchase_completed", new Dictionary<string, object>
        {
            ["amount"] = req.Amount,
            ["currency"] = "USD",
        });
        return Ok(new { ok = true });
    }
}
csharp

#4. Azure Functions

[Function("Checkout")]
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req)
{
    var data = await req.ReadFromJsonAsync<CheckoutRequest>();
    _vtilt.Capture(data!.UserId, "purchase_completed", new Dictionary<string, object> { ["amount"] = data.Amount });

    var res = req.CreateResponse(HttpStatusCode.OK);
    await res.WriteAsJsonAsync(new { ok = true });
    return res;
}
csharp

#Next steps

  • Identify & alias — full identification model.
  • Event forwarding — fan events out to GA4, Meta CAPI, PostHog.
  • Reverse proxy — block-resistant ingestion.
PreviousJavaIntegration guidesNextRustIntegration guides

On this page

  • 1. Configure
  • 2. Capture client
  • 3. Capture events
  • 4. Azure Functions
  • Next steps