Table of Contents

Customer Experience Center

Let the customer view and interact with commerce-content

The Customer Experience Center is a paragraph app used to display and interact with commerce-related data in frontend, typically in list form and associated with a particular user - the logged in user. It is the successor to the old customer center app but has been simplified and built exclusively for ViewModel templates — template tags are not supported.

This app can list:

  • Orders
  • Carts
  • Quotes
  • Ledger entries
  • Recurring orders (subscriptions)

When you add this app to a paragraph you'll see a list of settings controlling how the app works: CEC-settings To configure the app:

  1. Select an order type to show - carts, ledger entries, orders, etc.
  2. Specify how you want to retrieve the items:
    • Own orders
    • Own orders and orders from users with same customer number
    • Own orders and orders made by users that current user can impersonate
    • Own orders and orders made while impersonating
  3. Use the Display-settings to set the orders per page. the sort by field and the sort direction
  4. Select the templates that control the layout in frontend:
    • List
    • Detail
  5. If relevant, select a page to shopping cart - you can then redirect customers to e.g. a product page when relevant

Templates

The templates you can select - List and Detail - are used to render a list of items and a detailed view of a single item, respectively. The app will show the details-template when an OrderId parameter is present in the query string, and the Email-template is

The templates use ViewModels for strongly-types Razor rendering:

List templates

@inherits ViewModelTemplate<OrderListViewModel>
<div class="container my-4">
  <form class="row g-2 mb-3" method="get">
    <div class="col-auto">
      <input type="text" name="FilterOrderId" class="form-control" placeholder="Order ID" />
    </div>
    <div class="col-auto">
      <select name="FilterOrderStateId" class="form-select" onchange="this.form.submit()">
        <option value="">All States</option>
        @foreach (var state in Dynamicweb.Ecommerce.Services.OrderStates.GetStatesByOrderType(Dynamicweb.Ecommerce.Orders.OrderType.Order))
        {
          <option value="@state.Id">@state.Name</option>
        }
      </select>
    </div>
    <div class="col-auto">
      <button type="submit" class="btn btn-primary">Search</button>
    </div>
  </form>

  <table class="table table-striped align-middle">
    <thead>
      <tr>
        <th>Placed</th>
        <th>Order ID</th>
        <th>Customer</th>
        <th class="text-end">Total</th>
        <th class="text-end">State</th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      @foreach (var order in Model.Orders)
      {
        <tr>
          <td>@order.CreatedAt.ToString("yyyy-MM-dd")</td>
          <td>@order.Id</td>
          <td>@order.CustomerName</td>
          <td class="text-end">@order.Price.PriceFormatted</td>
          <td class="text-end"><span class="badge bg-secondary">@order.StateName</span></td>
          <td class="text-end">
            <form method="post" action="/Default.aspx?ID=@Pageview.ID">
              <input type="hidden" name="CustomerCenterCmd" value="reorder" />
              <input type="hidden" name="OrderId" value="@order.Id" />
              <button class="btn btn-sm btn-outline-primary">Reorder</button>
            </form>
          </td>
        </tr>
      }
    </tbody>
  </table>

  @if (Model.PageCount > 1)
  {
    <nav>
      <ul class="pagination">
        @for (int i = 1; i <= Model.PageCount; i++)
        {
          <li class="page-item @(i == Model.CurrentPage ? "active" : "")">
            <a class="page-link" href="?PageNum=@i">@i</a>
          </li>
        }
      </ul>
    </nav>
  }
</div>

Details templates

The Details-template is shown when an OrderID-parameter is present in the query string. It inherits the OrderViewModel and a simple details-template could look like this:

@using Dynamicweb.Rendering
@using Dynamicweb.Ecommerce.Frontend
@inherits ViewModelTemplate<OrderViewModel>

<div class="col-md-12">
    <h3>@Model.Id</h3>
    <p>Date: @Model.CompletedDate</p>

    <!--Orderlines etc.-->
    <table class="table">
        <thead>
            <tr>
                <th>@Translate("Product_name", "Product name")</th>
                <th>@Translate("Quantity", "Quantity")</th>
                <th>@Translate("Price", "Price")</th>
                <th></th>
            </tr>
        </thead>

        <tbody>
            @foreach (var line in Model.OrderLines)
            {
                <tr>
                    <td>
                        @line.ProductName
                        @if (line.ProductVariantName != "")
                        {
                            @: (@line.ProductVariantName)
                        }

                        @if (!string.IsNullOrWhiteSpace(@line.UnitId))
                        {
                            @: (@line.UnitId)
                        }
                        <!--Order line fields-->
                        @foreach (var field in line.OrderLineFields)
                        {
                            if (!string.IsNullOrWhiteSpace(@field.Value.ToString()))
                            {
                                <div style="font-size:12px;"><i>@field.Key.ToString()): @field.Value.ToString()</i></div>
                            }
                        }
                    </td>
                    <td>
                        @if (line.OrderLineType.ToString() == "1")
                        {
                            <span></span>
                        }
                        else
                        {
                            @line.Quantity
                        }
                    </td>
                    <td>@line.TotalPriceWithProductDiscounts.PriceWithVatFormatted</td>

                    <td>
                    </td>
                </tr>
            }
        </tbody>

        <tfoot>
            <tr>
                <td>Shipping (@Model.ShippingMethod.Name)</td>
                <td></td>
                <td>@Model.ShippingFee.PriceWithVatFormatted</td>
                <td></td>
            </tr>
            <tr>
                <td>Payment (@Model.PaymentMethod.Name)</td>
                <td></td>
                <td>@Model.PaymentFee.PriceWithVatFormatted</td>
                <td></td>
            </tr>

            <tr class="total">
                <th>Total</th>
                <th></th>
                <th>@Model.Price.PriceWithVatFormatted</th>
                <th></th>
            </tr>
        </tfoot>

    </table>

    <div class="row g-0">
        <div class="col-md-6 mb-4">
            <h4>Shipped To</h4>
            <div>@Model.CustomerFirstName @Model.CustomerSurname</div>
            <div>@Model.CustomerAddress</div>
            <div>@Model.CustomerZip @Model.CustomerCity</div>
            <div>@Model.CustomerCountry</div>
        </div>
        <div class="col-md-6 mb-4">
            <h4>Billed to</h4>
            <div>@Model.DeliveryFirstName @Model.DeliverySurname</div>
            <div>@Model.DeliveryAddress</div>
            <div>@Model.DeliveryZip @Model.DeliveryCity</div>
            <div>@Model.DeliveryCountry</div>
        </div>
    </div>

</div>

Customer Center commands

In your templates you can use Customer Center commands to post information to the app and perform actions. You can post commands:

  • Via a URL with CustomerCenterCmd and other parameters.
  • Via a form with CustomerCenterCmd as a field.

You can see a list of commands and how to use them below.

Reorder

The Reorder-command adds products from a previous order to the current cart:

<a href="?CustomerCenterCmd=Reorder&OrderId=@Model.Id">Add order to cart</a>

AcceptQuote

The AcceptQuote-command allows a user to accept a quote:

<a href="?CustomerCenterCmd=AcceptQuote&QuoteId={QuoteId}">Accept quote</a>

Query string filtering

The Customer Experience Center app accepts the following query string parameters - they can be used to filter the list of items returned:

Parameter Example Purpose
PageNum ?PageNum=2 Paging (1‑based).
SortBy ?SortBy=Price Overrides paragraph Sort by field.
SortOrder ?SortOrder=Desc Sort direction.
PageSize ?PageSize=50 Overrides paragraph page size.
FilterOrderStateId ?FilterOrderStateId=OS2 Filter by Order State ID.
FilterFromDate ?FilterFromDate=2025-08-01 Filter by OrderDate >=.
FilterToDate ?FilterToDate=2025-08-30 Filter by OrderDate <=.
FilterOrderId ?FilterOrderId=ORDER123 Exact order id search.
FilterText ?FilterText=abc Free text search.
FilterCustomerNumber ?FilterCustomerNumber=CUST-42 Exact customer number.
FilterCustomerName ?FilterCustomerName=Jane Doe Exact customer name.
FilterProductId ?FilterProductId=PROD1 Orders containing product id.
FilterProductNumber ?FilterProductNumber=SKU-1 Orders containing product number.
FilterProductName ?FilterProductName=Widget Orders containing product name.
FilterPriceAmountFrom ?FilterPriceAmountFrom=100 Minimum total price.
FilterPriceAmountTo ?FilterPriceAmountTo=500 Maximum total price.
FilterOrderCurrencyCode ?FilterOrderCurrencyCode=EUR,USD One or more currency codes.
SwitchRetrieveBy ?SwitchRetrieveBy=1 Toggles UseCustomerNumber.

A couple of implicit filters are also used:

  • Shop is auto‑set from current area (Area.EcomShopId)
  • The Completed state is derived from the Order type setting
To top