Sitecore Discover – Prepare your Product and Category Feed TAB-Delimited Text Files

Sitecore Discover offers powerful product search and recommendation functionalities, elevating the overall customer experience on your website. You may receive a test product dataset upon gaining access to the Customer Engagement Portal (CEC) of Sitecore Discover, which serves as the administration portal. Your initial priority is to update this product data to align with your specific set of products.

According to the documentation, each catalog requires two types of feeds, both provided in a TAB-delimited text file format:

Your product data may exist in different formats, such as XLS or JSON files, or it could be acquired dynamically through an API in an alternative format. In the case of an XLS file, you can convert it to a TAB-delimited text file easily. However, if the product data is in another format like JSON or XML, pre-processing is necessary before uploading the files to Sitecore Discover.

In this blog post, we’ll consider that our product data is stored in Sitecore OrderCloud and can be obtained as JSON through an API. Additionally, there is existing test data in the Sitecore Discover portal that we intend to replace. The entire procedure will follow these steps:

While exploring Sitecore GitHub repositories, I couldn’t locate any project or library that addressed this specific need. It appears to be a common situation for any customer considering the use of Sitecore OrderCloud and Sitecore Discover. Thus, I took the initiative to develop my own solution and contribute it to the community. The subsequent sections of this blog post provide a concise introduction to the C# console applications I created.

Let’s take a technical dive into this!

Product Data Feed Specification

Sitecore Discover utilizes standardized product attributes that enable platform-wide features and capabilities. These attributes are fundamental to functionalities like analytics, built-in recipes, site contexts, specialized facet experiences, and more.

In one of my previous blog posts, I deployed the Sitecore OrderCloud instance using Sitecore Demo Portal. I am utilizing the same PLAY! Shop instance and calling the “/me/products” Sitecore OrderCloud API call to get the product data in JSON format. For simplicity purposes, I am storing the complete output as a local file. Once I have the data in the file, all I need to do is write some data models and deserialize JSON as local C# objects as follows:

 string json = file.ReadToEnd();

 var data = JsonConvert.DeserializeObject<ProductDataItems>(json);

The following C# code converts the product data objects to the TAB-delimited text file using the product data specification for Sitecore Discover.

public static void ConvertToTabFile(ProductDataItems data)
        {
            try
            {
                
                string tab = "\t";
                
                string[] headerList = { 
                                        ProductFeedHeaders.product_group.ToString(), 
                                        ProductFeedHeaders.name.ToString(),
                                        ProductFeedHeaders.product_url.ToString(),
                                        ProductFeedHeaders.image_url.ToString(),
                                        ProductFeedHeaders.description.ToString(),
                                        ProductFeedHeaders.sku.ToString(),
                                        ProductFeedHeaders.sku_name.ToString(),
                                        ProductFeedHeaders.sku_url.ToString(),
                                        ProductFeedHeaders.sku_image_url.ToString(),
                                        ProductFeedHeaders.sku_description.ToString(),
                                        ProductFeedHeaders.ccids.ToString(),
                                        ProductFeedHeaders.price.ToString(),
                                        ProductFeedHeaders.final_price.ToString(),
                                        ProductFeedHeaders.is_active.ToString(),
                                        ProductFeedHeaders.brand.ToString() 
                                    };
                string detail = "";                
                string fileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"Data\product_data_tab_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt");
                using (var sw = new StreamWriter(fileName, false))
                {

                    string header = string.Join(tab, headerList);
                    foreach (var product in data.Items)
                    {
                        string cleanDescription = Regex.Replace(product.Description, "<.*?>", String.Empty);
                        string[] lineList =
                        {
                         product.ID,
                         product.Name,
                         product.XP?.ProductUrl,
                         product.XP?.Images?.FirstOrDefault()?.Url,
                         cleanDescription.Replace("\n",string.Empty),
                         product.ID,
                         product.Name,
                         product.XP?.ProductUrl,
                         product.XP?.Images?.FirstOrDefault()?.Url,
                         cleanDescription.Replace("\n",string.Empty),
                         product.XP?.CCID,                         
                         product.PriceSchedule?.PriceBreaks?.FirstOrDefault()?.Price.ToString(),
                         product.PriceSchedule?.PriceBreaks?.FirstOrDefault()?.Price.ToString(),
                         "1",
                         product.XP?.Brand
                    };

                        string line = string.Join(tab, lineList);

                        detail += Environment.NewLine + line;
                    }

                    sw.Write(header + detail);
                    sw.Close();
                    Console.WriteLine("File Created:" + fileName);

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Problem converting file" + ex.Message);

            }
        }

The complete project is given at GitHub – Generate Product Feed for you to clone and modify as per your input data structure. Build & run the solution to get the output path to the file locally:

Build & Run the project to get the file path

Open the text file via XLS to make sure all data records are coming through as expected:

Category Data Feed Specfication

Like the product data, the category data feed has its own specifications and requires a separate TAB-delimited text file, I can get the category data in JSON format for the PLAY! Shop demo instance by calling the “/me/categories” API call. 

Again, for simplicity, I stored the category data as a local file, created its data models, and deserialized it as local C# objects. The following C# code converts the category data objects to the TAB text file using the category data specification for Sitecore Discover.

 public static void ConvertToTabFile(CategoryDataItems data)
        {
            try
            {
                string tab = "\t";               
                string[] headerList = {
                                        CategoryFeedHeaders.ccid.ToString(),
                                        CategoryFeedHeaders.name.ToString(),
                                        CategoryFeedHeaders.url_path.ToString(),
                                        CategoryFeedHeaders.parent_ccid.ToString(),
                                        CategoryFeedHeaders.seo_name.ToString()
                                        
                                        
                                    };
                string detail = "";
                string fileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"Data\category_data_tab_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt");
                using (var sw = new StreamWriter(fileName, false))
                {

                    string header = string.Join(tab, headerList);
                    foreach (var category in data.Items)
                    {
                        
                        string[] lineList =
                        {
                            category.ID,
                            category.Name,
                            category.URLPath,
                            category.ParentID ?? string.Empty,
                            category.SEOName
                          
                        };
                    

                        string line = string.Join(tab, lineList);

                        detail += Environment.NewLine + line;
                    }

                    sw.Write(header + detail);
                    sw.Close();
                    Console.WriteLine("File Created:" + fileName);

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Problem converting file" + ex.Message);

            }
        }

While the general process remains consistent for both product and category data, there will be variations in the input and output data. Therefore, I found it more convenient to develop two distinct, independent projects to handle each separately. You can find the complete code for the category project at GitHub – Generate Category Feed. Build & run the solution to get the output path to the file locally:

Open the text file via XLS to make sure all data records are coming through as expected:

After obtaining the two TAB delimited text files containing the product and category feeds, the subsequent action is to upload them using SFTP (Secure File Transfer Protocol). Your Sitecore Discover representative will provide the necessary SFTP details for the process.
For production environments, it is recommended to upload the complete feed at least once within 24 hours to account for any additions or removals of products. Additionally, for intermediate or “On Publish” event changes, you should utilize the Incremental Feed API to push real-time updates to Sitecore Discover promptly.

That’s all for today!

Thanks

References:

1 – Preparing, uploading, and managing your data

2 – Product data feed specifications

3 – Category data feed specifications

4 – https://github.com/naveed-ahmad-biz/SitecoreDiscover.GenerateProductFeed

5 – https://github.com/naveed-ahmad-biz/SitecoreDiscover.GenerateCategoryFeed