clarity-js
Version:
An analytics library that uses web page interactions to generate aggregated insights
64 lines (60 loc) • 3.16 kB
text/typescript
import { Dimension, Metric, Setting } from "@clarity-types/data";
import { Constant, JsonLD } from "@clarity-types/layout";
import * as dimension from "@src/data/dimension";
import * as metric from "@src/data/metric";
const digitsRegex = /[^0-9\.]/g;
/* JSON+LD (Linked Data) Recursive Parser */
export function ld(json: any): void {
for (let key of Object.keys(json)) {
let value = json[key];
if (key === JsonLD.Type && typeof value === "string") {
value = value.toLowerCase();
/* Normalizations */
value = value.includes(JsonLD.Article) || value.includes(JsonLD.Posting) ? JsonLD.Article : value;
switch (value) {
case JsonLD.Article:
case JsonLD.Recipe:
dimension.log(Dimension.SchemaType, json[key]);
dimension.log(Dimension.AuthorName, json[JsonLD.Creator]);
dimension.log(Dimension.Headline, json[JsonLD.Headline]);
break;
case JsonLD.Product:
dimension.log(Dimension.SchemaType, json[key]);
dimension.log(Dimension.ProductName, json[JsonLD.Name]);
dimension.log(Dimension.ProductSku, json[JsonLD.Sku]);
if (json[JsonLD.Brand]) { dimension.log(Dimension.ProductBrand, json[JsonLD.Brand][JsonLD.Name]); }
break;
case JsonLD.AggregateRating:
if (json[JsonLD.RatingValue]) {
metric.max(Metric.RatingValue, num(json[JsonLD.RatingValue], Setting.RatingScale));
metric.max(Metric.BestRating, num(json[JsonLD.BestRating]));
metric.max(Metric.WorstRating, num(json[JsonLD.WorstRating]));
}
metric.max(Metric.RatingCount, num(json[JsonLD.RatingCount]));
metric.max(Metric.ReviewCount, num(json[JsonLD.ReviewCount]));
break;
case JsonLD.Offer:
dimension.log(Dimension.ProductAvailability, json[JsonLD.Availability]);
dimension.log(Dimension.ProductCondition, json[JsonLD.ItemCondition]);
dimension.log(Dimension.ProductCurrency, json[JsonLD.PriceCurrency]);
dimension.log(Dimension.ProductSku, json[JsonLD.Sku]);
metric.max(Metric.ProductPrice, num(json[JsonLD.Price]));
break;
case JsonLD.Brand:
dimension.log(Dimension.ProductBrand, json[JsonLD.Name]);
break;
}
}
// Continue parsing nested objects
if (value !== null && typeof(value) === Constant.Object) { ld(value); }
}
}
function num(input: string | number, scale: number = 1): number {
if (input !== null) {
switch (typeof input) {
case Constant.Number: return Math.round((input as number) * scale);
case Constant.String: return Math.round(parseFloat((input as string).replace(digitsRegex, Constant.Empty)) * scale);
}
}
return null;
}