Jak stworzyć banner z rekomendacjami w edytorze kodu
Edytor kodu umożliwia tworzenie dynamicznych banerów z rekomendacjami produktów przy użyciu kombinacji HTML, CSS, JavaScript i składni Razor. Z jego pomocą wyświetlisz spersonalizowane rekomendacje produktów bezpośrednio na swojej stronie lub w kampaniach e-mail.
Nazwy produktów w rekomendacjach zostaną wyświetlone jako ’@products[0]?.Name’, ponieważ obsługujący je kod nie jest przetwarzany bezpośrednio w edytorze .
Jeśli chcesz przetestować banner zawierający rzeczywiste dane produktów, skorzystaj z opcji Podgląd na żywo lub przetestuj banner bezpośrednio na swojej stronie.
Wspierane technologie
Edytor kodu pozwala na użycie następujących technologii:
- HTML5 – użyj do nadania struktury bannerowi.
- CSS3 – użyj do nadania indywidualnego wyglądu i responsywności.
- JavaScript – pozwoli dodać elementy interaktywne i dynamiczne.
- Składnia Razor – obsługuje logikę rekomendacji po stronie serwera, pozwala na wiązanie danych (data binding) za pomocą bloków „@{}”.
Pobieranie rekomendacji produktowych
Użyj następującego wyrażenia w bloku kodu, który ma wyświetlić rekomendacje:
@{
ExpertSender.Cdp.Common.Interfaces.DynamicContent.IProduct[] products = Model.GetRecommendedProducts(4).ToArray();
}
Ten kod pobiera maksymalnie 4 polecane produkty i zapisuje je w tablicy. Liczbę tę możesz dostosować do wymagań projektu banera.
Dostępne zmienne produktów
W tablicy poniżej znajdziesz zmienne dla każdej cechy produktu:
Zmienna | Typ | Opis | Jak stosować? |
Id | string | Unikalny identyfikator produktu | products[0].Id |
Name | string | Nazwa / tytuł produktu | products[0]?.Name |
ImageUrl | string | Adres URL obrazka przedstawiającego produkt | products[0]?.ImageUrl |
Url | string | Adres URL strony produktu | products[0]?.Url |
PriceS | string | Cena regularna w formacie string | products[0]?.PriceS |
SalePrice | string | Cena po obniżce w formacie string | products[0]?.SalePriceS |
OmnibusPriceS | string | Necna Omnibus (wymagana przez UE) | products[0]?.OmnibusPriceS |
CurrencySymbol | string | Symbol waluty (€, $, £, etc.) | products[0]?.CurrencySymbol |
Przykłady użycia
Sprawdź, czy produkt istnieje i wyświetl cenę po obniżce
@if (products[0] != null)
{
Produkt wyświetli się w tym miejscu
}
Sprawdź, czy cena po obniżce może być wyświetlona
Aby wyświetlić produkty z obniżoną ceną, sprawdź, czy zarówno cena regularna, jak i obniżona są dostępne dla danego produktu.
@if (!string.IsNullOrWhiteSpace(products[0]?.SalePriceS))
{
@products[0]?.SalePriceS @products[0]?.CurrencySymbol
}
else
{
@products[0]?.PriceS @products[0]?.CurrencySymbol
}
Wyświetl cenę Omnibus, jeśli jest dostępna
Wyświetlanie ceny Omnibus jest wymagane przez Unię Europejską, gdy polecasz produkty o obniżonej cenie.
@if (!string.IsNullOrWhiteSpace(products[0]?.OmnibusPriceS))
{
Najniższa cena z 30 dni: @products[0]?.OmnibusPriceS @products[0]?.CurrencySymbol
}
Oblicz i wyświetl obniżkę procentową
@{
decimal regularPrice = 0;
decimal salePrice = 0;
decimal discountPercentage = 0;
if (decimal.TryParse(products[0]?.PriceS, out regularPrice) &&
decimal.TryParse(products[0]?.SalePriceS, out salePrice) &&
regularPrice > 0 && salePrice > 0)
{
discountPercentage = Math.Round(((regularPrice - salePrice) / regularPrice) * 100, 0);
}
}
@if (discountPercentage > 0)
{
-@discountPercentage%
}
Pełna logika wyświetlania cen
Poniżej znajdziesz przykład obsługujący wszystkie scenariusze cenowe:
@if (!string.IsNullOrWhiteSpace(rec2[0]?.SalePriceS))
{
@rec2[0]?.SalePriceS @rec2[0]?.CurrencySymbol
@rec2[0]?.PriceS @rec2[0]?.CurrencySymbol
@if (!string.IsNullOrWhiteSpace(rec2[0]?.OmnibusPriceS))
{
@rec2[0]?.OmnibusPriceS @rec2[0]?.CurrencySymbol
}
}
else
{
@rec2[0]?.PriceS @rec2[0]?.CurrencySymbol
}
Pętla przez wszystkie produkty
Oto jak przejść przez wszystkie pobrane produkty i wyświetlić ich właściwości:
@{ ExpertSender.Cdp.Common.Interfaces.DynamicContent.IProduct[] products = Model.GetRecommendedProducts(4).ToArray();
}
@for (int i = 0; i < products.Length; i++)
{
if (products[i] != null)
{
@products[i].Id
@products[i].Name
@products[i].ImageUrl
@products[i].Url
@products[i].PriceS
@products[i].SalePriceS
@products[i].OmnibusPriceS
@products[i].CurrencySymbol
}
}
Przykładowa struktura banneru
<style>
.banner-header {
text-align: center;
padding: 20px;
background: white;
}
.banner-header h1 {
color: #2c3e50;
font-size: 24px;
margin-bottom: 5px;
font-weight: 600;
}
.banner-header p {
color: #7f8c8d;
font-size: 14px;
margin: 0;
}
.expertsender-banner {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 0;
width: 100%;
max-width: 1200px;
margin: 0 auto;
background: white;
box-sizing: border-box;
}
.banner-title {
grid-column: 1 / -1;
text-align: center;
font-size: 32px;
color: #2c3e50;
margin: 40px 0 30px 0;
font-weight: 300;
letter-spacing: -0.5px;
}
.product-card {
background: white;
padding: 30px 20px;
text-align: center;
transition: all 0.3s ease;
position: relative;
display: flex;
flex-direction: column;
height: 520px;
border-right: 1px solid #f1f3f4;
}
.product-card:last-child {
border-right: none;
}
.product-card:hover {
background: #fafbfc;
transform: translateY(-2px);
}
.discount-badge {
position: absolute;
top: 20px;
right: 20px;
background: #e74c3c;
color: white;
padding: 6px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 600;
box-shadow: 0 2px 8px rgba(231, 76, 60, 0.25);
}
.product-image {
width: 220px;
height: 220px;
object-fit: cover;
border-radius: 8px;
margin: 0 auto 20px auto;
transition: transform 0.3s ease;
background: #f8f9fa;
}
.product-card:hover .product-image {
transform: scale(1.02);
}
.product-name {
font-size: 18px;
font-weight: 500;
color: #2c3e50;
margin-bottom: 15px;
height: 50px;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
line-height: 1.4;
}
.price-section {
margin-bottom: 25px;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
.current-price {
font-size: 24px;
font-weight: 600;
color: #2c3e50;
margin-bottom: 5px;
}
.sale-price {
font-size: 24px;
font-weight: 600;
color: #e74c3c;
margin-bottom: 5px;
}
.original-price {
font-size: 16px;
text-decoration: line-through;
color: #95a5a6;
}
.buy-button {
background: #2c3e50;
color: white;
padding: 12px 32px;
border: none;
border-radius: 4px;
text-decoration: none;
display: inline-block;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
margin-top: auto;
}
.buy-button:hover {
background: #34495e;
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(44, 62, 80, 0.25);
}
.code-section {
margin-top: 40px;
background: white;
padding: 30px;
margin-left: 20px;
margin-right: 20px;
border-radius: 8px;
border: 1px solid #e9ecef;
}
.code-section h3 {
color: #2c3e50;
margin-bottom: 20px;
font-size: 18px;
font-weight: 500;
}
.code-block {
background: #f8f9fa;
color: #2c3e50;
padding: 20px;
border-radius: 6px;
overflow-x: auto;
font-family: 'Courier New', monospace;
font-size: 13px;
line-height: 1.6;
border: 1px solid #e9ecef;
}
@media (max-width: 768px) {
.product-card {
border-right: none;
border-bottom: 1px solid #f1f3f4;
height: auto;
min-height: 420px;
}
.product-card:last-child {
border-bottom: none;
}
.banner-title {
font-size: 28px;
margin: 30px 0 20px 0;
}
}
@media (max-width: 480px) {
.expertsender-banner {
grid-template-columns: 1fr;
}
.product-image {
width: 200px;
height: 200px;
}
}
</style>
@{
ExpertSender.Cdp.Common.Interfaces.DynamicContent.IProduct[] products = Model.GetRecommendedProducts(4).ToArray();
}
<div class="expertsender-banner">
<h3 class="banner-title">Featured Products</h3>
@foreach (var product in products)
{
<div class="product-card">
@if (decimal.TryParse(product?.PriceS, out decimal regularPrice) &&
decimal.TryParse(product?.SalePriceS, out decimal salePrice) &&
regularPrice > 0 && salePrice > 0)
{
<div class="discount-badge">@Math.Round(((regularPrice - salePrice) / regularPrice) * 100, 0)% OFF</div>
}
<img src="@product?.ImageUrl" alt="@product?.Name" class="product-image">
<div class="product-name">@product?.Name</div>
<div class="price-section">
@if (!string.IsNullOrWhiteSpace(product?.SalePriceS))
{
<div class="sale-price">@product?.SalePriceS @product?.CurrencySymbol</div>
<div class="original-price">@product?.PriceS @product?.CurrencySymbol</div>
}
else
{
<div class="current-price">@product?.PriceS @product?.CurrencySymbol</div>
}
</div>
<a href="@product?.Url" class="buy-button">Shop Now</a>
</div>
}
</div>
Podgląd banneru:
Tabela debugowania danych produktów
Ta tabela jest przydatna do debugowania i sprawdzania cech produktu zwróconych przez silnik rekomendacji.
Wyświetla wszystkie dostępne dane produktu w ustrukturyzowanym formacie iułatwia weryfikację, czy API zwraca oczekiwane informacje.
@{
ExpertSender.Cdp.Common.Interfaces.DynamicContent.IProduct[] products = Model.GetRecommendedProducts(4).ToArray();
}
<style>
table.custom-table {
border-collapse: collapse;
width: 100%;
}
table.custom-table, table.custom-table th, table.custom-table td {
border: 1px solid black;
}
table.custom-table th, table.custom-table td {
padding: 8px;
}
</style>
<table class="custom-table">
<thead>
<tr>
<th>Product</th>
<th>Image</th>
<th>Name</th>
<th>Link</th>
<th>ID</th>
<th>Regular Price</th>
<th>Sale Price</th>
<th>Omnibus Price</th>
</tr>
</thead>
<tbody>
@foreach (var product in products.Where(p => p != null).Select((p, index) => new { Product = p, Index = index }))
{
<tr>
<td>Product @product.Index</td>
<td><img src="@product.Product.ImageUrl" alt="Product @product.Index" width="100"/></td>
<td>@product.Product.Name</td>
<td><a href="@product.Product.Url">@product.Product.Url</a></td>
<td>@product.Product.Id</td>
<td>@product.Product.PriceS @product.Product.CurrencySymbol</td>
<td>@product.Product.SalePriceS @product.Product.CurrencySymbol</td>
<td>@product.Product.OmnibusPriceS @product.Product.CurrencySymbol</td>
</tr>
}
</tbody>
</table>
Najlepsze praktyki
- Aby zapobiec błędom, zawsze używaj operatorów warunkowych null (?.) podczas uzyskiwania dostępu do właściwości produktu.
- Przed wyświetleniem treści sprawdź, czy występują wartości null lub puste.
- Stosuj zasady projektowania responsywnego, aby upewnić się, że Twoje banery będą działać na wszystkich urządzeniach.
- Przetestuj swoje banery przy użyciu różnej liczby zwróconych produktów. API może zwrócić mniej produktów niż żądano.
- Podczas implementacji weź pod uwagę stany ładowania i stany puste.