@embedreach/components 0.3.44 → 0.3.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21134,6 +21134,13 @@ const createCampaignMetricsFactory = (campaignId, campaignName, channel, busines
21134
21134
  const roas = baseMetrics.spend > 0 ? baseMetrics.revenue / baseMetrics.spend : 0;
21135
21135
  const cpc = baseMetrics.clicks > 0 ? baseMetrics.spend / baseMetrics.clicks : 0;
21136
21136
  const ctr = baseMetrics.impressions > 0 ? baseMetrics.clicks / baseMetrics.impressions : 0;
21137
+ const leadsFromAds = Math.round(baseMetrics.leads * 0.7);
21138
+ const costPerLead = leadsFromAds > 0 ? baseMetrics.spend / leadsFromAds : 0;
21139
+ const leadToPurchaseRate = baseMetrics.leads > 0 ? baseMetrics.conversions / baseMetrics.leads * 100 : 0;
21140
+ const totalValueOfConvertedLeads = baseMetrics.revenue;
21141
+ const averageLeadValue = baseMetrics.conversions > 0 ? totalValueOfConvertedLeads / baseMetrics.conversions : 0;
21142
+ const openLeads = baseMetrics.leads - baseMetrics.conversions;
21143
+ const totalValueOfOpenLeads = openLeads * averageLeadValue;
21137
21144
  return {
21138
21145
  id: campaignId,
21139
21146
  name: campaignName,
@@ -21145,6 +21152,12 @@ const createCampaignMetricsFactory = (campaignId, campaignName, channel, busines
21145
21152
  measured_conversions: baseMetrics.conversions,
21146
21153
  measured_revenue: baseMetrics.revenue,
21147
21154
  new_leads: baseMetrics.leads,
21155
+ leads_from_ads: leadsFromAds,
21156
+ cost_per_lead: costPerLead,
21157
+ lead_to_purchase_rate: leadToPurchaseRate,
21158
+ total_value_of_open_leads: totalValueOfOpenLeads,
21159
+ total_value_of_converted_leads: totalValueOfConvertedLeads,
21160
+ average_lead_value: averageLeadValue,
21148
21161
  new_customers: baseMetrics.customers,
21149
21162
  customer_ltv: baseMetrics.ltv,
21150
21163
  roas,
@@ -21163,6 +21176,8 @@ const createChannelMetricsFactory = (businessId, channel, campaigns) => {
21163
21176
  impressions: acc.impressions + campaign.impressions,
21164
21177
  conversions: acc.conversions + campaign.measured_conversions,
21165
21178
  leads: acc.leads + campaign.new_leads,
21179
+ leadsFromAds: acc.leadsFromAds + (campaign.leads_from_ads || 0),
21180
+ convertedLeadValue: acc.convertedLeadValue + (campaign.total_value_of_converted_leads || 0),
21166
21181
  customers: acc.customers + campaign.new_customers,
21167
21182
  ltv: acc.ltv + campaign.customer_ltv * campaign.new_customers
21168
21183
  }),
@@ -21173,6 +21188,8 @@ const createChannelMetricsFactory = (businessId, channel, campaigns) => {
21173
21188
  impressions: 0,
21174
21189
  conversions: 0,
21175
21190
  leads: 0,
21191
+ leadsFromAds: 0,
21192
+ convertedLeadValue: 0,
21176
21193
  customers: 0,
21177
21194
  ltv: 0
21178
21195
  }
@@ -21181,6 +21198,11 @@ const createChannelMetricsFactory = (businessId, channel, campaigns) => {
21181
21198
  const roas = totals.spend > 0 ? totals.revenue / totals.spend : 0;
21182
21199
  const cpc = totals.clicks > 0 ? totals.spend / totals.clicks : 0;
21183
21200
  const ctr = totals.impressions > 0 ? totals.clicks / totals.impressions : 0;
21201
+ const costPerLead = totals.leadsFromAds > 0 ? totals.spend / totals.leadsFromAds : 0;
21202
+ const leadToPurchaseRate = totals.leads > 0 ? totals.conversions / totals.leads * 100 : 0;
21203
+ const averageLeadValue = totals.conversions > 0 ? totals.convertedLeadValue / totals.conversions : 0;
21204
+ const openLeads = totals.leads - totals.conversions;
21205
+ const totalValueOfOpenLeads = openLeads * averageLeadValue;
21184
21206
  return {
21185
21207
  business_id: businessId,
21186
21208
  ads_spend: totals.spend,
@@ -21189,6 +21211,12 @@ const createChannelMetricsFactory = (businessId, channel, campaigns) => {
21189
21211
  measured_conversions: totals.conversions,
21190
21212
  measured_revenue: totals.revenue,
21191
21213
  new_leads: totals.leads,
21214
+ leads_from_ads: totals.leadsFromAds,
21215
+ cost_per_lead: costPerLead,
21216
+ lead_to_purchase_rate: leadToPurchaseRate,
21217
+ total_value_of_open_leads: totalValueOfOpenLeads,
21218
+ total_value_of_converted_leads: totals.convertedLeadValue,
21219
+ average_lead_value: averageLeadValue,
21192
21220
  new_customers: totals.customers,
21193
21221
  customer_ltv: avgLtv,
21194
21222
  roas,
@@ -21904,6 +21932,33 @@ function scaleChannelMetrics(channelMetrics, options) {
21904
21932
  channelMetrics.new_leads = Math.round(
21905
21933
  channelMetrics.new_leads * scalingFactor
21906
21934
  );
21935
+ if (typeof channelMetrics.leads_from_ads === "number") {
21936
+ channelMetrics.leads_from_ads = Math.round(
21937
+ channelMetrics.leads_from_ads * scalingFactor
21938
+ );
21939
+ }
21940
+ if (typeof channelMetrics.total_value_of_converted_leads === "number") {
21941
+ channelMetrics.total_value_of_converted_leads = parseFloat(
21942
+ (channelMetrics.total_value_of_converted_leads * scalingFactor).toFixed(
21943
+ 2
21944
+ )
21945
+ );
21946
+ }
21947
+ if (typeof channelMetrics.leads_from_ads === "number" && channelMetrics.leads_from_ads > 0) {
21948
+ channelMetrics.cost_per_lead = parseFloat(
21949
+ (channelMetrics.ads_spend / channelMetrics.leads_from_ads).toFixed(2)
21950
+ );
21951
+ }
21952
+ if (typeof channelMetrics.total_value_of_converted_leads === "number" && typeof channelMetrics.lead_to_purchase_rate === "number" && channelMetrics.lead_to_purchase_rate > 0) {
21953
+ channelMetrics.average_lead_value = parseFloat(
21954
+ (channelMetrics.total_value_of_converted_leads / (channelMetrics.new_leads * (channelMetrics.lead_to_purchase_rate / 100))).toFixed(2)
21955
+ );
21956
+ }
21957
+ if (typeof channelMetrics.total_value_of_open_leads === "number") {
21958
+ channelMetrics.total_value_of_open_leads = parseFloat(
21959
+ (channelMetrics.total_value_of_open_leads * scalingFactor).toFixed(2)
21960
+ );
21961
+ }
21907
21962
  channelMetrics.date_range = {
21908
21963
  start: actualStartDate,
21909
21964
  end: actualEndDate
@@ -21922,6 +21977,26 @@ function scaleChannelMetrics(channelMetrics, options) {
21922
21977
  (campaign.measured_revenue * scalingFactor).toFixed(2)
21923
21978
  );
21924
21979
  campaign.new_leads = Math.round(campaign.new_leads * scalingFactor);
21980
+ if (typeof campaign.leads_from_ads === "number") {
21981
+ campaign.leads_from_ads = Math.round(
21982
+ campaign.leads_from_ads * scalingFactor
21983
+ );
21984
+ }
21985
+ if (typeof campaign.total_value_of_converted_leads === "number") {
21986
+ campaign.total_value_of_converted_leads = parseFloat(
21987
+ (campaign.total_value_of_converted_leads * scalingFactor).toFixed(2)
21988
+ );
21989
+ }
21990
+ if (typeof campaign.total_value_of_open_leads === "number") {
21991
+ campaign.total_value_of_open_leads = parseFloat(
21992
+ (campaign.total_value_of_open_leads * scalingFactor).toFixed(2)
21993
+ );
21994
+ }
21995
+ if (typeof campaign.leads_from_ads === "number" && campaign.leads_from_ads > 0) {
21996
+ campaign.cost_per_lead = parseFloat(
21997
+ (campaign.ads_spend / campaign.leads_from_ads).toFixed(2)
21998
+ );
21999
+ }
21925
22000
  campaign.date_range = {
21926
22001
  start: actualStartDate,
21927
22002
  end: actualEndDate
@@ -22481,6 +22556,148 @@ const measureAndAcquireHandlers = [
22481
22556
  }
22482
22557
  });
22483
22558
  }),
22559
+ http.get(`${HOSTNAME}/api/orders/source-info/totals-by-field`, (req) => {
22560
+ const url = new URL(req.request.url);
22561
+ const startDateString = url.searchParams.get("startDate");
22562
+ const endDateString = url.searchParams.get("endDate");
22563
+ const groupByParam = url.searchParams.get("groupBy");
22564
+ const groupBy = groupByParam || "primary_source";
22565
+ const platformData = getSandboxDataForPlatform(currentSandboxPlatformId);
22566
+ const baseSourceInfo = platformData.orderSourceInfoTotals;
22567
+ if (!baseSourceInfo || !startDateString || !endDateString) {
22568
+ return HttpResponse.json(
22569
+ {
22570
+ success: false,
22571
+ message: "Sandbox data for order source info not found or missing date params"
22572
+ },
22573
+ { status: 400 }
22574
+ );
22575
+ }
22576
+ const { requestedDays } = parseDateRange(
22577
+ startDateString,
22578
+ endDateString,
22579
+ 90
22580
+ );
22581
+ const basePeriodDays = 60;
22582
+ const scalingFactor = requestedDays / basePeriodDays;
22583
+ const scaledSourceBreakdown = baseSourceInfo.sourceBreakdown.map(
22584
+ (item) => ({
22585
+ ...item,
22586
+ count: Math.round(item.count * scalingFactor),
22587
+ amount: parseFloat((item.amount * scalingFactor).toFixed(2))
22588
+ })
22589
+ );
22590
+ const scaledTotalCount = Math.round(
22591
+ baseSourceInfo.totalCount * scalingFactor
22592
+ );
22593
+ const scaledTotalAmount = parseFloat(
22594
+ (baseSourceInfo.totalAmount * scalingFactor).toFixed(2)
22595
+ );
22596
+ const getGroupKeyAndMeta = (item) => {
22597
+ switch (groupBy) {
22598
+ case "source_type":
22599
+ return { key: item.source_type };
22600
+ case "utm_medium": {
22601
+ let medium = "(none)";
22602
+ if (item.source_type === "paid") {
22603
+ medium = "cpc";
22604
+ } else if (item.source_type === "organic_search") {
22605
+ medium = "organic";
22606
+ } else if (item.source_type === "social") {
22607
+ medium = "social";
22608
+ } else if (item.source_type === "referral") {
22609
+ medium = "referral";
22610
+ }
22611
+ return { key: medium };
22612
+ }
22613
+ case "utm_campaign": {
22614
+ let campaign = "Direct Traffic";
22615
+ if (item.source_type === "paid") {
22616
+ if (item.primary_source.toLowerCase().includes("google")) {
22617
+ campaign = "Search Campaigns";
22618
+ } else if (item.primary_source.toLowerCase().includes("facebook")) {
22619
+ campaign = "Social Campaigns";
22620
+ } else {
22621
+ campaign = "Paid Campaigns";
22622
+ }
22623
+ } else if (item.source_type === "organic_search") {
22624
+ campaign = "Organic Search";
22625
+ } else if (item.source_type === "social") {
22626
+ campaign = "Social Organic";
22627
+ } else if (item.source_type === "referral") {
22628
+ campaign = "Referral Traffic";
22629
+ } else if (item.source_type === "direct") {
22630
+ campaign = "Direct Traffic";
22631
+ } else if (item.source_type === "unknown") {
22632
+ campaign = "Unknown";
22633
+ }
22634
+ return { key: campaign };
22635
+ }
22636
+ case "referrer_domain": {
22637
+ const lower = item.primary_source.toLowerCase();
22638
+ let domain = "direct";
22639
+ if (lower.includes("google")) {
22640
+ domain = "google.com";
22641
+ } else if (lower.includes("facebook")) {
22642
+ domain = "facebook.com";
22643
+ } else if (lower.includes("bing")) {
22644
+ domain = "bing.com";
22645
+ } else if (lower.includes("yahoo")) {
22646
+ domain = "yahoo.com";
22647
+ } else if (lower.includes("yelp")) {
22648
+ domain = "yelp.com";
22649
+ } else if (lower.includes("directory")) {
22650
+ domain = "industry-directory.com";
22651
+ } else if (item.source_type === "direct") {
22652
+ domain = "(direct)";
22653
+ } else if (item.source_type === "unknown") {
22654
+ domain = "(unknown)";
22655
+ }
22656
+ return { key: domain };
22657
+ }
22658
+ case "primary_source":
22659
+ default:
22660
+ return { key: item.primary_source, source_type: item.source_type };
22661
+ }
22662
+ };
22663
+ const breakdownMap = /* @__PURE__ */ new Map();
22664
+ for (const item of scaledSourceBreakdown) {
22665
+ const { key, source_type } = getGroupKeyAndMeta(item);
22666
+ const existing = breakdownMap.get(key);
22667
+ if (existing) {
22668
+ existing.count += item.count;
22669
+ existing.amount = parseFloat(
22670
+ (existing.amount + item.amount).toFixed(2)
22671
+ );
22672
+ } else {
22673
+ breakdownMap.set(key, {
22674
+ value: key,
22675
+ source_type,
22676
+ count: item.count,
22677
+ amount: item.amount
22678
+ });
22679
+ }
22680
+ }
22681
+ const breakdown = Array.from(breakdownMap.values());
22682
+ const breakdownTotalCount = breakdown.reduce(
22683
+ (sum, item) => sum + item.count,
22684
+ 0
22685
+ );
22686
+ const breakdownTotalAmount = parseFloat(
22687
+ breakdown.reduce((sum, item) => sum + item.amount, 0).toFixed(2)
22688
+ );
22689
+ const finalTotalCount = scaledTotalCount || breakdownTotalCount;
22690
+ const finalTotalAmount = scaledTotalAmount || breakdownTotalAmount;
22691
+ return HttpResponse.json({
22692
+ success: true,
22693
+ message: `Success (Sandbox Order Source Info Totals By Field - Grouped by ${groupBy} for ${requestedDays} days)`,
22694
+ data: {
22695
+ totalCount: finalTotalCount,
22696
+ totalAmount: finalTotalAmount,
22697
+ breakdown
22698
+ }
22699
+ });
22700
+ }),
22484
22701
  http.get(`${HOSTNAME}/api/orders/source-info`, (req) => {
22485
22702
  const url = new URL(req.request.url);
22486
22703
  const startDateString = url.searchParams.get("startDate");