@blotoutio/edgetag-sdk-browser 1.66.2 → 1.68.0

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.
Files changed (2) hide show
  1. package/index.js +52 -23
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -1495,7 +1495,7 @@
1495
1495
  referrer: getReferrer(destination),
1496
1496
  search: getSearch(destination),
1497
1497
  locale: getLocale(),
1498
- sdkVersion: "1.66.2" ,
1498
+ sdkVersion: "1.68.0" ,
1499
1499
  ...(payload || {}),
1500
1500
  };
1501
1501
  let storage = {};
@@ -1619,7 +1619,6 @@
1619
1619
 
1620
1620
  const preparePayloadWithConversion = (payloadData, currencySettings) => {
1621
1621
  const currency = payloadData['currency'];
1622
- const value = parseFloat(payloadData['value']);
1623
1622
  if (!currency || !currencySettings) {
1624
1623
  return null;
1625
1624
  }
@@ -1627,15 +1626,31 @@
1627
1626
  if (!conversion) {
1628
1627
  return null;
1629
1628
  }
1629
+ // Convert the whole money breakdown, not just `value`: applyPurchaseValueMode
1630
+ // recomputes value from grossValue/taxCost/shippingCost, app-lovin reads the
1631
+ // same fields, and discount_value nets against item_price downstream.
1632
+ const convert = (obj, key) => {
1633
+ const amount = parseFloat(obj[key]);
1634
+ if (amount) {
1635
+ obj[key] = parseFloat((amount * conversion.value).toFixed(3));
1636
+ }
1637
+ };
1630
1638
  payloadData['currency'] = conversion.to;
1631
- if (value) {
1632
- payloadData['value'] = parseFloat((value * conversion.value).toFixed(3));
1639
+ convert(payloadData, 'value');
1640
+ convert(payloadData, 'grossValue');
1641
+ convert(payloadData, 'taxCost');
1642
+ convert(payloadData, 'shippingCost');
1643
+ // predicted_ltv is a monetary string (Facebook custom_data); keep it a string.
1644
+ if (payloadData['predicted_ltv']) {
1645
+ const ltv = parseFloat(payloadData['predicted_ltv']);
1646
+ if (ltv) {
1647
+ payloadData['predicted_ltv'] = parseFloat((ltv * conversion.value).toFixed(3)).toString();
1648
+ }
1633
1649
  }
1634
1650
  if ('contents' in payloadData && Array.isArray(payloadData['contents'])) {
1635
1651
  for (const content of payloadData['contents']) {
1636
- if ('item_price' in content) {
1637
- content.item_price = parseFloat((content.item_price * conversion.value).toFixed(3));
1638
- }
1652
+ convert(content, 'item_price');
1653
+ convert(content, 'discount_value');
1639
1654
  }
1640
1655
  }
1641
1656
  return {
@@ -1770,14 +1785,28 @@
1770
1785
  }
1771
1786
  };
1772
1787
  // Dispatches a plugin's additional events. Mirrors the edge: each event is
1773
- // stamped with the emitting plugin (so it cannot reprocess itself) and limited
1774
- // to that plugin's scope.
1775
- const dispatchAdditionalEvents = (plugin, pluginScopes, events) => {
1788
+ // stamped with the emitting plugin and stage (so it cannot reprocess itself at
1789
+ // that stage or an earlier one) and limited to that plugin's scope.
1790
+ const dispatchAdditionalEvents = (plugin, pluginScopes, stage, events) => {
1776
1791
  const providerLimits = getPluginProviderLimits(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name]);
1777
1792
  for (const evt of events) {
1778
- handleTag(evt.eventName, evt.data, providerLimits, undefined, plugin.name);
1793
+ handleTag(evt.eventName, evt.data, providerLimits, undefined, plugin.name, stage);
1779
1794
  }
1780
1795
  };
1796
+ const stageOrder = {
1797
+ root: 0,
1798
+ channel: 1,
1799
+ instance: 2,
1800
+ };
1801
+ // The plugin that emitted an additional
1802
+ // event is suppressed at the emitting stage and every earlier one, but still
1803
+ // runs at later stages so it can post-process its own events.
1804
+ const isPluginSuppressed = (pluginName, pluginSource, pluginStage, stage) => {
1805
+ if (pluginName !== pluginSource) {
1806
+ return false;
1807
+ }
1808
+ return stageOrder[stage] <= stageOrder[pluginStage !== null && pluginStage !== void 0 ? pluginStage : 'instance'];
1809
+ };
1781
1810
  // Runs a channel/instance hook chain. The emitting plugin is excluded by the
1782
1811
  // caller's allow-list filter; additional events fire before any skip is applied
1783
1812
  // (matching the edge), and a skip is reported without mutating the final tag.
@@ -1803,7 +1832,7 @@
1803
1832
  variables: plugin.variables || {},
1804
1833
  });
1805
1834
  if (result === null || result === void 0 ? void 0 : result.additionalEvents) {
1806
- dispatchAdditionalEvents(plugin, pluginScopes, result.additionalEvents);
1835
+ dispatchAdditionalEvents(plugin, pluginScopes, hookName === 'tagChannel' ? 'channel' : 'instance', result.additionalEvents);
1807
1836
  }
1808
1837
  // Mark-and-continue, matching the edge (processPluginsChannel /
1809
1838
  // processPluginsInstance): a skip suppresses only the final tag; later
@@ -1837,7 +1866,7 @@
1837
1866
  // skip is applied, and skips are scoped — a global plugin marks every browser
1838
1867
  // instance, a scoped one only its resolved instances. The skip is a marker:
1839
1868
  // channel/instance hooks still run and only the final tag is suppressed.
1840
- const runRootPluginHooks = async (plugins, baseParams, pluginScopes, configuredTags, pluginSource) => {
1869
+ const runRootPluginHooks = async (plugins, baseParams, pluginScopes, configuredTags, pluginSource, pluginStage) => {
1841
1870
  var _a, _b;
1842
1871
  const payload = baseParams['payload'];
1843
1872
  let currentEventName = payload['eventName'];
@@ -1845,8 +1874,9 @@
1845
1874
  let currentProviders = baseParams['providers'];
1846
1875
  const skippedInstances = new Set();
1847
1876
  for (const plugin of plugins) {
1848
- if (plugin.name === pluginSource)
1877
+ if (isPluginSuppressed(plugin.name, pluginSource, pluginStage, 'root')) {
1849
1878
  continue;
1879
+ }
1850
1880
  const hook = plugin.rules.tagRoot;
1851
1881
  if (!hook)
1852
1882
  continue;
@@ -1861,7 +1891,7 @@
1861
1891
  variables: plugin.variables || {},
1862
1892
  });
1863
1893
  if (result === null || result === void 0 ? void 0 : result.additionalEvents) {
1864
- dispatchAdditionalEvents(plugin, pluginScopes, result.additionalEvents);
1894
+ dispatchAdditionalEvents(plugin, pluginScopes, 'root', result.additionalEvents);
1865
1895
  }
1866
1896
  if (result === null || result === void 0 ? void 0 : result.skipEvent) {
1867
1897
  const scopeSkipKeys = getScopedPluginSkipKeys(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name], configuredTags);
@@ -1900,7 +1930,7 @@
1900
1930
  skippedInstances,
1901
1931
  };
1902
1932
  };
1903
- const processTag = async (destination, eventName, data = {}, providers, options, pluginSource) => {
1933
+ const processTag = async (destination, eventName, data = {}, providers, options, pluginSource, pluginStage) => {
1904
1934
  var _a, _b;
1905
1935
  let currentEventName = eventName;
1906
1936
  if (!getSetting(destination, 'initialized')) {
@@ -1971,7 +2001,7 @@
1971
2001
  providers,
1972
2002
  settings: pluginSettings,
1973
2003
  utilities: pluginUtilities,
1974
- }, pluginScopes, configuredTags, pluginSource);
2004
+ }, pluginScopes, configuredTags, pluginSource, pluginStage);
1975
2005
  if (rootResult.providers !== undefined) {
1976
2006
  // eslint-disable-next-line no-param-reassign
1977
2007
  providers = rootResult.providers;
@@ -2010,8 +2040,7 @@
2010
2040
  // events still fire even when instances are skipped. All instances
2011
2041
  // share the same channel-level input (eventName/data), so a single
2012
2042
  // invocation is equivalent to running it per instance.
2013
- const channelPlugins = plugins.filter((plugin) => plugin.name !== pluginSource &&
2014
- isPluginAllowed(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name], providerId, null));
2043
+ const channelPlugins = plugins.filter((plugin) => !isPluginSuppressed(plugin.name, pluginSource, pluginStage, 'channel') && isPluginAllowed(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name], providerId, null));
2015
2044
  if (channelPlugins.length > 0) {
2016
2045
  const channelResult = await runPluginHook(channelPlugins, 'tagChannel', pluginScopes, {
2017
2046
  payload: {
@@ -2052,7 +2081,7 @@
2052
2081
  logger.log('GEO request region does not match the filter, skipping');
2053
2082
  continue;
2054
2083
  }
2055
- const instancePlugins = plugins.filter((plugin) => plugin.name !== pluginSource &&
2084
+ const instancePlugins = plugins.filter((plugin) => !isPluginSuppressed(plugin.name, pluginSource, pluginStage, 'instance') &&
2056
2085
  isPluginAllowed(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name], providerId, variable.tagName));
2057
2086
  if (instancePlugins.length > 0) {
2058
2087
  const instanceResult = await runPluginHook(instancePlugins, 'tagInstance', pluginScopes, {
@@ -2135,13 +2164,13 @@
2135
2164
  handleTag(additionalEventName, jsonClone(originalData || {}), originalProviders, options);
2136
2165
  }
2137
2166
  };
2138
- const handleTag = (eventName, data = {}, providers, options, pluginSource) => {
2167
+ const handleTag = (eventName, data = {}, providers, options, pluginSource, pluginStage) => {
2139
2168
  if (options === null || options === void 0 ? void 0 : options.destination) {
2140
- processTag(options.destination, eventName, data, providers, options, pluginSource).catch(logger.error);
2169
+ processTag(options.destination, eventName, data, providers, options, pluginSource, pluginStage).catch(logger.error);
2141
2170
  return;
2142
2171
  }
2143
2172
  getInstances().forEach((instance) => {
2144
- processTag(instance, eventName, data, providers, options, pluginSource).catch(logger.error);
2173
+ processTag(instance, eventName, data, providers, options, pluginSource, pluginStage).catch(logger.error);
2145
2174
  });
2146
2175
  };
2147
2176
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/edgetag-sdk-browser",
3
- "version": "1.66.2",
3
+ "version": "1.68.0",
4
4
  "description": "Browser SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",