Skip to content

Customize Commerce Connect

⏱ 35 minutes advanced
📜Advancedcommerce

The pre-built connectors handle standard product sync and transaction routing. Your business likely has requirements that go beyond the standard — custom product attributes, complex pricing logic, multi-currency handling, or proprietary API formats. Custom connectors and event handlers let you adapt Commerce Connect to your specific integration needs without forking the framework.

  1. Build a custom connector for a non-standard commerce platform
  2. Add custom data transformations for product sync
  3. Handle Commerce Connect events for real-time processing
  4. Extend the transaction proxy with custom logic
  5. Implement error handling and retry strategies

If your commerce platform does not have a pre-built connector, implement the ICommerceConnector interface.

Custom connector implementation
csharp
public class CustomPlatformConnector
    : ICommerceConnector
{
    private readonly HttpClient _httpClient;
    private readonly ConnectorOptions _options;

    public CustomPlatformConnector(
        HttpClient httpClient,
        IOptions<ConnectorOptions> options)
    {
        _httpClient = httpClient;
        _options = options.Value;
    }

    public async Task<IEnumerable<ExternalProduct>>
        GetProducts(SyncContext context)
    {
        var response = await _httpClient.GetAsync(
            $"{_options.ApiUrl}/products" +
            $"?modified_after={context.LastSyncUtc:O}");

        response.EnsureSuccessStatusCode();

        var data = await response.Content
            .ReadFromJsonAsync<ProductResponse>();

        return data.Products.Select(p =>
            new ExternalProduct
            {
                ExternalId = p.Id.ToString(),
                Name = p.Title,
                Description = p.BodyHtml,
                Slug = p.Handle,
                Categories = p.Collections,
                Variants = p.Variants.Select(v =>
                    MapVariant(v)).ToList(),
                Images = p.Images.Select(i =>
                    new ProductImage {
                        Url = i.Src, Alt = i.Alt
                    }).ToList()
            });
    }

    public async Task<CartResult> AddToCart(
        string variantId, int quantity,
        string sessionId)
    {
        var payload = new { variant_id = variantId,
            quantity, session_id = sessionId };

        var response = await _httpClient.PostAsJsonAsync(
            $"{_options.ApiUrl}/cart/add", payload);

        var result = await response.Content
            .ReadFromJsonAsync<CartResponse>();

        return new CartResult
        {
            Success = response.IsSuccessStatusCode,
            CartId = result.CartId,
            ItemCount = result.TotalItems
        };
    }
}

Register your custom connector in the service collection.

Register custom connector
csharp
services.AddCommerceConnect(options =>
{
    options.Platform = CommercePlatform.Custom;
})
.AddConnector<CustomPlatformConnector>();

Override the default data mapping when your commerce platform uses non-standard data structures.

Custom product transformer
csharp
public class CustomProductTransformer
    : IProductTransformer
{
    public CmsProduct Transform(
        ExternalProduct source)
    {
        var product = new CmsProduct
        {
            Name = source.Name,
            Code = source.ExternalId,
            UrlSlug = source.Slug,
            Description = SanitizeHtml(
                source.Description),
            Brand = source.Metadata
                .GetValueOrDefault("vendor", ""),
        };

        // Custom logic: generate search-friendly tags
        product.SearchTags = GenerateSearchTags(
            source.Name,
            source.Description,
            source.Categories);

        // Custom logic: map multi-currency pricing
        product.Prices = source.Variants
            .SelectMany(v => v.Prices
                .Select(p => new ProductPrice
                {
                    VariantCode = v.Sku,
                    Amount = p.Amount,
                    Currency = p.CurrencyCode,
                    CustomerGroup = p.PriceList
                }))
            .ToList();

        return product;
    }

    private string[] GenerateSearchTags(
        string name, string desc,
        IEnumerable<string> categories)
    {
        var words = $"{name} {desc}"
            .Split(' ', StringSplitOptions
                .RemoveEmptyEntries)
            .Where(w => w.Length > 3)
            .Distinct(StringComparer.OrdinalIgnoreCase)
            .Take(20);

        return categories.Concat(words).ToArray();
    }
}

Subscribe to events that fire during sync and transaction operations. Use events for logging, notifications, cache invalidation, or triggering downstream processes.

Event handlers
csharp
public class CommerceConnectEventHandlers
{
    public static void Register(
        ICommerceConnectEvents events)
    {
        // After product sync completes
        events.OnProductSynced += async (product) =>
        {
            // Invalidate CDN cache for updated pages
            await CdnPurge.PurgeProduct(
                product.UrlSlug);

            // Send to ODP for customer analytics
            await OdpTracker.TrackProductUpdate(
                product.Code, product.Name,
                product.Categories);
        };

        // After category structure changes
        events.OnCategorySynced += async (category) =>
        {
            await NavigationCache.Invalidate();
        };

        // When a sync error occurs
        events.OnSyncError += (error) =>
        {
            Logger.Error(
                "Sync failed for {ProductId}: {Error}",
                error.ExternalId, error.Message);

            if (error.IsTransient)
                error.ScheduleRetry(
                    TimeSpan.FromMinutes(5));
        };

        // After order is placed through proxy
        events.OnOrderPlaced += async (order) =>
        {
            await OdpTracker.TrackPurchase(
                order.CustomerId,
                order.OrderTotal,
                order.LineItems);
        };
    }
}

Add custom logic to cart and checkout operations before they reach your commerce platform.

Transaction proxy extension
csharp
public class CustomTransactionProxy
    : ITransactionProxy
{
    private readonly ICommerceConnector _connector;
    private readonly IExperimentationService _experiments;

    public async Task<CartResult> AddToCart(
        AddToCartRequest request)
    {
        // Run experimentation variation assignment
        var variation = await _experiments
            .GetVariation("checkout-flow-test",
                request.SessionId);

        // Apply variation-specific logic
        if (variation == "express-checkout")
        {
            request.Metadata["checkout_type"] = "express";
        }

        // Track the add-to-cart event in ODP
        await OdpTracker.Track("add_to_cart", new
        {
            product_id = request.VariantId,
            quantity = request.Quantity,
            session_id = request.SessionId
        });

        return await _connector.AddToCart(
            request.VariantId,
            request.Quantity,
            request.SessionId);
    }
}

Build resilient sync and transaction handling with retry logic and circuit breakers.

Resilient connector wrapper
csharp
services.AddHttpClient<CustomPlatformConnector>()
    .AddPolicyHandler(Policy
        .Handle<HttpRequestException>()
        .OrResult<HttpResponseMessage>(
            r => r.StatusCode == HttpStatusCode
                .TooManyRequests)
        .WaitAndRetryAsync(3,
            attempt => TimeSpan.FromSeconds(
                Math.Pow(2, attempt)),
            onRetry: (outcome, delay, attempt, ctx) =>
            {
                Logger.Warning(
                    "Retry {Attempt} after {Delay}s",
                    attempt, delay.TotalSeconds);
            }))
    .AddPolicyHandler(Policy
        .Handle<HttpRequestException>()
        .CircuitBreakerAsync(5,
            TimeSpan.FromMinutes(1)));
PatternWhen to useImplementation
Multi-source catalogProducts come from multiple systemsRegister multiple connectors with source priority
Price overrideOptimizely controls some pricesImplement IPriceOverrideProvider
Inventory aggregationStock from multiple warehousesCustom IInventoryAggregator
Custom checkout fieldsB2B-specific checkout dataExtend the transaction proxy request model
Selective syncOnly sync specific categoriesAdd SyncFilter to connector options