How to create an online catalogue for your business at a much lower cost
Tags: webdev, productivity, architecture, startup
Published: 2022-01-13 13:51:29

## Growing your business with an online catalogue?

You have a business, you have a website - of sorts, and you want to have your products on your website.

You have researched a large range of Ecommerce providers and think these are who you can use to build your website. There is a snag though, you don't want their website on your website. Integrating it is not possible or very complicated. Do you look for a headless CMS solution or perhaps find a software solutions provider to integrate your EPOS into your website? What about Amazon, eBay, or Facebook? There are many companies providing APIs where you can have a software developer write substantial code to integrate it into your website.

## About this Article

This article aims to cover how we at Info Rhino have evolved our own Web Data Platform to permit content, articles, products, reports to be less coupled to the website content management system. Furthermore, when working with external product catalogues, whether they are an onsite EPOS or one of the Ecommerce providers online, we don't want to try embedding this into the website itself and instead focus more on the data. I aim to show how taking a slightly different approach to developing website applications can leave you less vulnerable to product upgrades too and dramatically improve Return on Investment (ROE).

I am working on a startup, in addition to building products and services for my Limited Company. Am always happy to hear from people who may have synergy, even commercial vision.

We explain how we have incorporated this into our own Web Data Platform - [https://www.inforhino.co.uk/services/web-data-platform-launch](https://www.inforhino.co.uk/services/web-data-platform-launch) . If you are looking to design your own website with product integration you may care to look at this or instead take a similar approach for yourselves. The one important thing is that the approaches I have taken to build this platform dramatically lowers the cost because the focus is more on the data and content, rather than the technology.

Whatever you decide, I hope you find this article informative.

### The challenge of attention and presence online

It is really important to think about the challenge of getting found, when you are a small to medium sized business with a number of products and services. You have a product catalogue, perhaps this is made available to Amazon, Stripe, PayPal or some other platform. The challenge, as we are facing ourselves at Info Rhino and findigl - how do we grow attention to our

## Publishing your EPOS data to an online product catalogue - the technology

### The technical challenges involved

A business which has an Electronic Purchase Order System (EPOS) will face the challenge of deciding how to connect your product stock with publicly facing websites. Almost certainly a shopping-cart website will expose an API whereby you can publish data to and pull from. At that point, it is likely you will need to write some translation code to map that data to your website front-end.

In essence, this is a data management issue - migrating data to and pulling data from different websites and databases. The bigger challenge is breaking changes - upgrades. There is not a simple one answer to this and typically involves a lot more work.

### The advantage of data and web application skills

If you have skills in Business Intelligence and Application Development, the technical challenges become more of a data challenge. Instead the challenge is moving information between systems.

At Info Rhino, our focus is on considering data to be open and less about being in many repositories. Instead of writing code against an API, transforming it in code, publishing it to the Ecommerce website API, and having a significant development overhead. Why not try the following?

Have an expected json format for products and push this data to disk, letting the website take this data to display on the website. An extension on this is to have metadata to help add extra information about the products to permit it to be laid out in a much more relevant location and categorised. There may still be some API work needed, but wherever possible, we prefer to get straight to the underlying data in a database or alternate source.

As a developer, we may wonder what the benefits of the above approach are. Instead of several extra steps, saving content to a secured folder (disk/FTP) cuts out an immense amount of overhead worrying about publishing to an API. The website monitors the folder for products and pulls it into their product cache. We configure views to handle and display this content which in turn, allows us to embed this into the website with comparative ease.

## Our implementation within our Web Data Platform Website CMS Product at Info Rhino

Our Web Data Platform sits alongside a CMS in .Net Core - Piranha CMS. As excellent as Piranha CMS is, there is something disconcerting about "putting all your eggs in one basket". It is because it is fairly easy (although it takes a lot of time to develop) to add new layouts and fields to the CMS that all good developers should be concerned. What happens if Piranha CMS upgrades to a point where the current content and CMS information is no longer valid? We cannot simply avoid the CMS altogether, so we took the approach to have as much data held outside the CMS as possible and to incorporate View Components and Partial Views. If we can work more with this data, despite it being messier to maintain, we can minimise the pain when  we upgrade our CMS or potentially even move to a different CMS altogether.

### You're probably doing it all wrong?

Ouch - the critical thing to understand is that the ways that people think about putting together an Ecommerce and Data Platform with a CMS is almost undoubtedly wrong. The typical approach for systems integration to be undertaken is for developers to focus on extending APIs, welding themselves to the host architecture/frameworks.

Instead of building client/domain specific functionality into a website, it has to be about generic and reusable components. Whilst we cannot isolate ourselves from the dependency upon a Content Management System, we can do as much as possible to make significant parts of the website fairly portable.

One way to do this is to use the CMS for content management, and to allow for sensible configuration which other non-CMS components can interact with. What we will do in this article, is to explain how we have handled product/service cataloguing to feature within the website. We will include snippets but not the entire code base as this will get too heavy for an article which is more about concepts.

In-short, we make it all about the data. In many ways, this follows from my reading up on Promise Theory many years ago. We have no need to understand expectation of how a system behaves, we just know that it does its work and tells us it is done. Taking this a step further, if we have data, we know that is the data that is needed and that is it. The system does what it wants to do with that data.

### High Level Design Diagram
![Online Product Catalogue High Level Design](https://www.inforhino.co.uk/Images/Articles/OnlineProductCatalogHLDD.jpg)
The diagram itself may be quite involved, but we have to imagine the many additional steps we would need to add if we were working with APIs. On the left side of the HLDD is a middleware component which interacts with upstream sources. They could themselves be an API, a database, or even - as in our case at Info Rhino - manually configured json files. We aren't dealing with thousands of products.

### Some json data examples for configuration

Again, we don't want to go overboard here and include partial parts from the json files. The data here is what will be in our relaunched property platform - findigl, due Feb 2022, so don't get too confused by the content please.

#### Products.json
```json
[
{
"ProductKey": "Articles",
"ProductName": "Articles",
"Description": ["Feature your ideas, insights, information about your business on a property platform separate to your website, on our searchable directory."],
"ImageUrl": "",
"Links": "",
"TermUnit": "months",
"Term": 12,
"Currency": "£",
"MaximumQuantity": 700,
"AvailableNumber": 12,
"ProductFeatures" : [ {
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Article Directory Listing"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Reach your audience"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Demonstrate expertise"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Publish your guides"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Backlinking possibilities"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Link from Social Media"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Link from your website"
}
],
"Discounts": null
,"UnitPrice" : 60
},
{
"ProductKey": "ArticleArchive",
"ProductName": "Article Archive",
"Description": ["Customers wishing for their article to remain on findigl longer than 1 year can archive them. They are still on findigl, but not in our directory."],
"ImageUrl": "",
"Links": "",
"TermUnit": "months",
"Term": 12,
"Currency": "£",
"MaximumQuantity": 700,
"AvailableNumber": -1,
"ProductFeatures" : [{
"IconCss": "<i class='fa fa-minus-square' aria-hidden='true'></i>",
"Feature": "Not in directory"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Reach your audience"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Demonstrate expertise"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Publish your guides"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Backlinking possibilities"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Link from Social Media"
},
{
"IconCss": "<i class='fa fa-check-circle' aria-hidden='true'></i>",
"Feature": "Link from your website"
}],
"Discounts": null
,"UnitPrice" : 15
}]
```
#### Package.json
```json
[{
"PackageKey": "ArticlesPackage",
"PackageTitle": null,
"Currency": null,
"PackageProducts": [
{
"Number": 1,
"ProductKey": "Articles"
}
,
{
"Number": 1,
"ProductKey": "ArticleArchive"
}
]
,
"IncludePackageTotalPrice" : false,
"ShowSummaryProducts" : false
}
,
{
"PackageKey": "ReportsPackage",
"PackageTitle": null,
"Currency": null,
"PackageProducts":
[
{
"Number": 1,
"ProductKey": "Reports"
}
] ,
"IncludePackageTotalPrice" : false,
"ShowSummaryProducts" : false
}
]
```
#### PackageGroup.json
```json
[
{
"Title": "Articles Packages",
"Paragraphs": ["The easiest way for your business to feature on findigl is to write an article and put it on findigl","Articles remain on our findigl article's directory for one year. Once that year is past, optionally retain the article on our platform through a permalink for a smaller fee.","This should improve SEO and backlinking over time (no guarantees)."],
"Slugs": [{"Slug" :"articles","After" : true},{"Slug" :"commercial/plans-and-pricing","After" : true}],
"PackageKeys": ["ArticlesPackage"],
"Image": null
}
,
{
"Title": "Reports Package",
"Paragraphs": ["Throughout findigl, we feature reports which are interactive and user-friendly. They provide information which can be analysed.","The same technology we use to publish our own reports on is available for customers wishing to report their information on findigl.","Paying for one report is a placeholder to allow reports to be updated daily for the package duration."],
"Slugs": [{"Slug" :"markets/market-reports","After" : true},{"Slug" :"markets","After" : true},{"Slug" :"commercial/plans-and-pricing","After" : true}],
"PackageKeys": ["ReportsPackage"],
"Image": null
}
,
{
"Title": "findigl Site Presence Options",
"Paragraphs": ["To have your own presence and content dominantly featuring on findigl, take a look at these products.","Add to your business' reputation by featuring your; ideas, stories, success, results in one place."
,"You supply information in our expected card format (content plus images) and depending upon the package chosen will determine where you feature."],
"Slugs": [{"Slug" :"commercial/plans-and-pricing","After" : true},{"Slug" :"cards","After" : true}],
"PackageKeys": ["ArticlesPackage"],
"Image": null
}
]
```
#### Some C# Interfaces of the dotnet core app around Package Products

To avoid going into the implementation, we will include some of the interfaces we use to make the online catalogue appear within our website.

public interface IManagedPackageModelRetrieverService
```csharp
{

ICacheService<IEnumerable<PackageGroupModel>> cacheService { get; set; }

IPackageModelKeyHelper packageModelKeyHelper { get; set; }

IPackageModelRetrieverService packageModelRetrieverService { get; set; }

IEnumerable<PackageGroupModel> GetPackageGroupModel(PageSlug Slug);

IEnumerable<PackageGroupModel> Reload(PageSlug Slug);

}
```
Whilst the code is not detailed here, it should be clear that we have a Package Group Model object which can be retrieved via a page slug. Our view will invoke the View Component if the slug matches.

View Component Razor Markup for Package Products

The reason we use Razor is to facilitate Web Crawlers easier access to the markup. Another thing outside of this page which is built into our Web Data Platform is a Schema.Org plugin. Again, we have a folder where we can push schema.org definition files to be incorporated into the website. This is recommended for SEO enhancements.
```html
@model IEnumerable<....Models.Products.PackageGroupModel>

@inject ...Models.Display.DisplaySetting display

@inject ....Models.Display.PackageProductConfig packageProductConfig
@functions{
string BackgroundImage(string ImageUrl)
{
if (!string.IsNullOrEmpty(ImageUrl))
{
return $" background: url('{Url.Content(ImageUrl)}');fixed center no-repeat;background-size: cover;min-height:300px;width:100vw;";
}
return "";
}
}
@foreach (var packageProduct in Model)
{
@:<div class="ir-package-detail">
@:<div class="row">
@:<div class="col-md-12" style="@(BackgroundImage(packageProduct.Image))">
@:<h2>@(packageProduct.Title)</h2>
foreach (var paragraph in packageProduct.Paragraphs)
{
@:<p>@(paragraph)</p>
}
@:</div>
if (packageProduct.PackageModels.Any(y => y.ShowSummaryProducts == true))
{
foreach (var packageModel in packageProduct.PackageModels)
{
@:<div class="col-md-4">
@:<div class="card h-100 shadow">
@:<div class="card-header">
@:<h5>@(packageModel.PackageTitle)</h5>
if (packageModel.IncludePackageTotalPrice == true)
{
@:<h5>@($"{packageModel.Currency}{packageModel.PackagePrice}")</h5>
}
@:</div>
@:<div class="card-body">
foreach (var product in packageModel.Products)
{
@:<p>@($"{product.Currency}{product.UnitPrice} * {product.Number} of {product.ProductName}")</p>
var links = product.Links ?? new List<IRWebsiteCMS.Models.Display.Link>();
if (links.Count() > 0)
{
var firstLink = links.ElementAt(0);
/*We get the first link*/
@:<a href="@(firstLink.UrlTarget)" target="@(firstLink.Target)">@(firstLink.Caption)</a>
}
}
@:</div>
@:</div>
@:</div>
}
}
if (packageProductConfig.ShowProductDetail == true)
{
var productKeys = packageProduct.PackageModels.SelectMany(x => x.Products).Select(x => x.ProductKey).Distinct();
@await Component.InvokeAsync(nameof(ProductList), new IRWebsiteCMS.Models.Products.ProductListParameter { ProductKeys = productKeys, Products = null })
}
@:</div>
@:</div>
}
```
The above Razor does the job, am certain it could be improved, but importantly, we can include a set of products per Package. We are able to show them on the website in different locations. For example, on our Property Platform - findigl, we can include our "Articles" Package on the Articles page. On Our Reports page, we can include our Reports Package. We will include all our Products on our Products page without considering the packages.

## Possible Amazon use case

Rather than repeat what has been presented in other articles, I included a link to an Amazon Ecommerce article about their API. It should not be too hard to imagine doing the following;

-   Writing a small C# Console application to connect your Product Catalogue to Amazon (Through their API).
-   Set up an FTP Folder on your web server (Or secure Folder).
-   Pull content from Amazon and save it to that Folder.
-   Let your website take that content and display it within the site.

Nothing would stop you from including links from your own website to its Amazon listing either.

## Thinking about this Promise based approach to including online catalogues on your website

I have to focus on value and implementing my solutions as quickly as I can. Right now, I have three platforms which uses my web data platform - Info Rhino, findigl, and an upcoming platform - Crypto Statto. What cannot happen is building very specific domain functionality into the web data platform and so reusable components capable of taking data, interpreting it and showing it within the website works best for me.

We have avoided adding many more layers, sacrificing some of the control to instead work with the data rather than; multiple APIs, Ecommerce Websites, Databases, Workflow Engines, Authentication and Authorisation when all we really want to do is to increase the presence of our products online.

### Reference Material

[https://elfsight.com/blog/2020/05/how-to-use-amazon-ecommerce-api-examples-and-pricing/](https://elfsight.com/blog/2020/05/how-to-use-amazon-ecommerce-api-examples-and-pricing/)


> Written with [StackEdit](https://stackedit.io/).