@blotoutio/edgetag-sdk-js 1.60.0 → 1.61.1

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 (3) hide show
  1. package/index.cjs.js +34 -20
  2. package/index.mjs +34 -20
  3. package/package.json +1 -1
package/index.cjs.js CHANGED
@@ -1470,7 +1470,7 @@ const getStandardPayload = (destination, payload) => {
1470
1470
  referrer: getReferrer(destination),
1471
1471
  search: getSearch(destination),
1472
1472
  locale: getLocale(),
1473
- sdkVersion: "1.60.0" ,
1473
+ sdkVersion: "1.61.1" ,
1474
1474
  ...(payload || {}),
1475
1475
  };
1476
1476
  let storage = {};
@@ -1662,16 +1662,26 @@ const sendTag = (destination, { eventName, eventId, data, providerData, provider
1662
1662
  // by the plugin's identity `${providerId}||${name}` (which is carried in the
1663
1663
  // plugin object's `name`). A missing scope means the plugin is global.
1664
1664
  //
1665
- // Mirrors the edge getAllowedPlugins per-item logic: at instance level the
1666
- // scripts allow-list wins, otherwise fall back to the providers allow-list.
1665
+ // Mirrors the edge getAllowedPlugins: an instance-scoped plugin runs only for
1666
+ // its exact instance (instance stage) or the channel its scripts imply (channel
1667
+ // stage); a plugin counts as global only when it has NEITHER providers NOR
1668
+ // scripts — an empty providers list alone does not make it global.
1667
1669
  const isPluginAllowed = (scope, providerId, instanceName) => {
1668
1670
  if (!scope) {
1669
1671
  return true;
1670
1672
  }
1671
- if (instanceName && scope.scripts.length > 0) {
1673
+ const isInstanceScoped = scope.scripts.length > 0;
1674
+ // Instance stage for an instance-scoped plugin: only its exact instance.
1675
+ if (instanceName && isInstanceScoped) {
1672
1676
  return scope.scripts.includes(`${providerId}||${instanceName}`);
1673
1677
  }
1674
- return scope.providers.length === 0 || scope.providers.includes(providerId);
1678
+ // Channel stage (or instance stage for a global/channel-scoped plugin).
1679
+ // A plugin is global only when it has NEITHER providers NOR scripts; an
1680
+ // instance-scoped plugin still runs for the channel its scripts imply — it
1681
+ // is NOT global just because its providers list is empty.
1682
+ const isGlobal = scope.providers.length === 0 && !isInstanceScoped;
1683
+ const impliesChannel = scope.scripts.some((script) => script.split('||')[0] === providerId);
1684
+ return isGlobal || scope.providers.includes(providerId) || impliesChannel;
1675
1685
  };
1676
1686
  // Mirrors the edge processPluginsRoot skip scope: a global plugin (no scope)
1677
1687
  // skips every browser instance (null), a scoped plugin skips only the instances
@@ -1967,30 +1977,34 @@ const processTag = async (destination, eventName, data = {}, providers, options,
1967
1977
  skipped: rootSkippedInstances.has(`${providerId}||${variable.tagName}`),
1968
1978
  });
1969
1979
  }
1970
- // Channel phase (processPluginsChannel): tagChannel runs once per
1971
- // instance, regardless of skip/consent/geo, so its side effects and
1972
- // additional events still fire on skipped instances.
1980
+ // Channel phase (processPluginsChannel): tagChannel runs ONCE per
1981
+ // channel and the result fans out to every instance, mirroring the
1982
+ // edge. It runs regardless of skip/consent/geo so its additional
1983
+ // events still fire even when instances are skipped. All instances
1984
+ // share the same channel-level input (eventName/data), so a single
1985
+ // invocation is equivalent to running it per instance.
1973
1986
  const channelPlugins = plugins.filter((plugin) => plugin.name !== pluginSource &&
1974
1987
  isPluginAllowed(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name], providerId, null));
1975
1988
  if (channelPlugins.length > 0) {
1989
+ const channelResult = await runPluginHook(channelPlugins, 'tagChannel', pluginScopes, {
1990
+ payload: {
1991
+ eventName: currentEventName,
1992
+ data,
1993
+ eventId,
1994
+ },
1995
+ context: pluginContext,
1996
+ settings: pluginSettings,
1997
+ providerId,
1998
+ utilities: pluginUtilities,
1999
+ });
1976
2000
  for (const variable of variables) {
1977
2001
  const state = instanceStates.get(variable.tagName);
1978
- const channelResult = await runPluginHook(channelPlugins, 'tagChannel', pluginScopes, {
1979
- payload: {
1980
- eventName: state.eventName,
1981
- data: state.data,
1982
- eventId,
1983
- },
1984
- context: pluginContext,
1985
- settings: pluginSettings,
1986
- providerId,
1987
- utilities: pluginUtilities,
1988
- });
1989
2002
  if (channelResult.skip) {
1990
2003
  state.skipped = true;
1991
2004
  }
1992
2005
  state.eventName = channelResult.eventName;
1993
- state.data = channelResult.data;
2006
+ // Clone per instance so later per-instance mutation stays isolated
2007
+ state.data = jsonClone(channelResult.data);
1994
2008
  }
1995
2009
  }
1996
2010
  // Instance phase (processPluginsInstance + tag send): consent/geo gate,
package/index.mjs CHANGED
@@ -1468,7 +1468,7 @@ const getStandardPayload = (destination, payload) => {
1468
1468
  referrer: getReferrer(destination),
1469
1469
  search: getSearch(destination),
1470
1470
  locale: getLocale(),
1471
- sdkVersion: "1.60.0" ,
1471
+ sdkVersion: "1.61.1" ,
1472
1472
  ...(payload || {}),
1473
1473
  };
1474
1474
  let storage = {};
@@ -1660,16 +1660,26 @@ const sendTag = (destination, { eventName, eventId, data, providerData, provider
1660
1660
  // by the plugin's identity `${providerId}||${name}` (which is carried in the
1661
1661
  // plugin object's `name`). A missing scope means the plugin is global.
1662
1662
  //
1663
- // Mirrors the edge getAllowedPlugins per-item logic: at instance level the
1664
- // scripts allow-list wins, otherwise fall back to the providers allow-list.
1663
+ // Mirrors the edge getAllowedPlugins: an instance-scoped plugin runs only for
1664
+ // its exact instance (instance stage) or the channel its scripts imply (channel
1665
+ // stage); a plugin counts as global only when it has NEITHER providers NOR
1666
+ // scripts — an empty providers list alone does not make it global.
1665
1667
  const isPluginAllowed = (scope, providerId, instanceName) => {
1666
1668
  if (!scope) {
1667
1669
  return true;
1668
1670
  }
1669
- if (instanceName && scope.scripts.length > 0) {
1671
+ const isInstanceScoped = scope.scripts.length > 0;
1672
+ // Instance stage for an instance-scoped plugin: only its exact instance.
1673
+ if (instanceName && isInstanceScoped) {
1670
1674
  return scope.scripts.includes(`${providerId}||${instanceName}`);
1671
1675
  }
1672
- return scope.providers.length === 0 || scope.providers.includes(providerId);
1676
+ // Channel stage (or instance stage for a global/channel-scoped plugin).
1677
+ // A plugin is global only when it has NEITHER providers NOR scripts; an
1678
+ // instance-scoped plugin still runs for the channel its scripts imply — it
1679
+ // is NOT global just because its providers list is empty.
1680
+ const isGlobal = scope.providers.length === 0 && !isInstanceScoped;
1681
+ const impliesChannel = scope.scripts.some((script) => script.split('||')[0] === providerId);
1682
+ return isGlobal || scope.providers.includes(providerId) || impliesChannel;
1673
1683
  };
1674
1684
  // Mirrors the edge processPluginsRoot skip scope: a global plugin (no scope)
1675
1685
  // skips every browser instance (null), a scoped plugin skips only the instances
@@ -1965,30 +1975,34 @@ const processTag = async (destination, eventName, data = {}, providers, options,
1965
1975
  skipped: rootSkippedInstances.has(`${providerId}||${variable.tagName}`),
1966
1976
  });
1967
1977
  }
1968
- // Channel phase (processPluginsChannel): tagChannel runs once per
1969
- // instance, regardless of skip/consent/geo, so its side effects and
1970
- // additional events still fire on skipped instances.
1978
+ // Channel phase (processPluginsChannel): tagChannel runs ONCE per
1979
+ // channel and the result fans out to every instance, mirroring the
1980
+ // edge. It runs regardless of skip/consent/geo so its additional
1981
+ // events still fire even when instances are skipped. All instances
1982
+ // share the same channel-level input (eventName/data), so a single
1983
+ // invocation is equivalent to running it per instance.
1971
1984
  const channelPlugins = plugins.filter((plugin) => plugin.name !== pluginSource &&
1972
1985
  isPluginAllowed(pluginScopes === null || pluginScopes === void 0 ? void 0 : pluginScopes[plugin.name], providerId, null));
1973
1986
  if (channelPlugins.length > 0) {
1987
+ const channelResult = await runPluginHook(channelPlugins, 'tagChannel', pluginScopes, {
1988
+ payload: {
1989
+ eventName: currentEventName,
1990
+ data,
1991
+ eventId,
1992
+ },
1993
+ context: pluginContext,
1994
+ settings: pluginSettings,
1995
+ providerId,
1996
+ utilities: pluginUtilities,
1997
+ });
1974
1998
  for (const variable of variables) {
1975
1999
  const state = instanceStates.get(variable.tagName);
1976
- const channelResult = await runPluginHook(channelPlugins, 'tagChannel', pluginScopes, {
1977
- payload: {
1978
- eventName: state.eventName,
1979
- data: state.data,
1980
- eventId,
1981
- },
1982
- context: pluginContext,
1983
- settings: pluginSettings,
1984
- providerId,
1985
- utilities: pluginUtilities,
1986
- });
1987
2000
  if (channelResult.skip) {
1988
2001
  state.skipped = true;
1989
2002
  }
1990
2003
  state.eventName = channelResult.eventName;
1991
- state.data = channelResult.data;
2004
+ // Clone per instance so later per-instance mutation stays isolated
2005
+ state.data = jsonClone(channelResult.data);
1992
2006
  }
1993
2007
  }
1994
2008
  // Instance phase (processPluginsInstance + tag send): consent/geo gate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/edgetag-sdk-js",
3
- "version": "1.60.0",
3
+ "version": "1.61.1",
4
4
  "description": "JS SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",