WeShareAI developer platform

WeShareAI is a rules-based contextual AI — system-level learning, no per-user profiling.

Overview

WeShareAI is the only platform that transforms a simple share action into a fully AI-powered, revenue-generating experience. More shares → more traffic → more revenue.

  • AI Smart Share Buttons adapt instantly to each visitor’s country, language, and content context — boosting clicks and shares. → boost shares with personalized, country & language–aware design.
  • AI Language Switching breaks language barriers in real time, unlocking global engagement across 194+ countries. → unlocks non-English audiences instantly, multiplying reach & traffic.
  • Post-share Ad Units turn sharing into monetization, delivering ads, rewards, or premium content right after the share. → convert traffic into direct revenue (ads, rewards, premium content).

Together, these innovations create smarter engagement, stronger revenue, and full privacy compliance — something no competitor offers. The result: higher engagement, global accessibility, and new monetization channels — all without cookies, tracking, or branding.

Privacy by default: No cookies, no IDs, no PII. Decisions are driven by non-identifying, ephemeral signals (e.g., browser language, IP-based country, page context).

How WeShareAI Differs from ShareThis and Similar Platforms

TL;DR: ShareThis runs AI in the data pipeline (audience modeling, data resale). WeShareAI brings AI to the front-end experience (real-time, contextual, privacy-first).

Many publishers ask: “But isn’t ShareThis also using AI and Machine Learning?” The short answer is yes — but in a completely different way. With ShareThis, the AI/ML primarily powers the backend data pipeline, where tools like PyTorch, Apache Spark ML, and AWS EMR process 1B+ daily events to build audience segments, run lookalike models, and feed advertisers with insights. The result is that their share widgets remain static; the “intelligence” is invisible to users and optimized for data products.

WeShareAI takes the opposite approach. Our intelligence is front-end and contextual, directly visible to users and publishers. Smart Share Buttons adapt in real time by country/region (different top networks across US/GR/JP/BR), language (auto-detect + translated labels, placeholders, thank-you messages), context (browser signals, environment, content type), and post-share logic (ads, rewards, smart CTAs). In other words, the UI/UX is the intelligence surface — not a distant data pipe.

From a stack perspective, ShareThis emphasizes scalable data infra — AWS, Kubernetes, Docker, BigQuery, MongoDB, DynamoDB, Elasticsearch, and AWS Lambda — which points to big-data ingestion, transformation, and monetization. By contrast, WeShareAI ships lightweight, plug-and-play JS modules (button.js, smart-weshare-ai.js, weshare-language-ai.js) where the contextual logic runs client-side, with privacy by design (no PII, no cookies) and transparent telemetry via GA4 (e.g., ai_activated).

The difference also shows up in philosophy and business model. ShareThis monetizes via data resale to advertisers; AI helps profile users and enrich data products — a path that carries higher compliance exposure. WeShareAI focuses on publisher empowerment: smarter sharing, post-share monetization, and global reach — all without collecting PII. Our system refines rules at the platform level using anonymized, aggregate signals, never per-user profiling.

In summary: ShareThis AI = backend, big data, audience profiling (invisible to users). WeShareAI AI = front-end, contextual, publisher-first (visible intelligence, privacy-first).
Tagline: ShareThis hides AI in the data pipeline. WeShareAI brings AI to the share button itself.

Smart Share Buttons (smart-weshare-ai.js)

What it does: Ranks & renders the most relevant networks per visitor using contextual signals (no cookies/PII).
Output: A sorted, minimal set of buttons → higher CTR with less clutter.
Fallback: If AI is unavailable, users still see a sensible default set.
AspectDetails
Inputs Browser language Coarse geo (country) Device Page context
Runtime logic Geo-aware presets per country via servicesByCountry → runtime country detection (endpoint e.g. /api/get-country.php, fallback to US) → per-visitor rendering inside AI placeholders (.e-mailit_btn_AI) → call into renderer e_mailit.parseButtons().
Telemetry Sends GA4 gtag events with country, selected_services, ai_activatedno PII.
Resilience MutationObserver waits for placeholders, performs deterministic replacement, re-runs if necessary; graceful defaults if a signal is missing.

Country presets & selection

A curated servicesByCountry map defines the most relevant networks per market (e.g., JP: LINE/Twitter, GR: Viber). At runtime the script resolves the visitor’s country, applies preset weights, and prunes/reorders to produce a compact, high-intent set.

json
{
  "US": ["Facebook","Twitter","WhatsApp","Messenger","Reddit"],
  "JP": ["LINE","Twitter","Facebook"],
  "GR": ["Viber","Facebook","Messenger","WhatsApp"],
  "PL": ["Facebook","Messenger","TikTok","WhatsApp"]  // trends adjust over time
}

Rendering flow (deterministic)

The Smart layer targets AI placeholders, injects the chosen services, and hands off to the core renderer. DOM safety is ensured via a MutationObserver that triggers once buttons are present and retries on dynamic pages.

html
<!-- Placeholder placed by the theme/CMS -->
<div class="e-mailit_btn_AI" data-max="6"></div>
javascript
// (excerpt) runtime replacement
const host = document.querySelectorAll('.e-mailit_btn_AI');
host.forEach(el => {
  // 1) choose services for this visitor
  const list = chooseServicesForVisitor({ country, lang, device, context });
  // 2) inject + call renderer
  el.innerHTML = renderServiceButtons(list);
  e_mailit.parseButtons(el);
});

Analytics (privacy-safe)

GA4 events capture AI activation and the networks rendered — useful for CTR analysis and platform-level learning. No user identifiers or cookies are used.

javascript
gtag('event', 'weshare_ai_render', {
  country: countryCode,
  selected_services: list.join(','),
  ai_activated: true
});

gtag('event', 'weshare_ai_click', {
  service: clickedService,
  ai_activated: true
});
What this proves: Context-aware selection per country, deterministic runtime replacement (no surprises), and transparent telemetry confirming AI activation and which services were shown — all with graceful fallbacks if signals are unavailable.

Language Switching

AI Language Loader (weshare-language-ai.min.js)

What it does: Detects the visitor’s language and prepares runtime translations for the UI.
Scope: UI labels, tooltips, calls-to-action (including thank-you messages).
Privacy: No PII, no cookies; uses only ephemeral, non-identifying signals.
AspectDetails
Language detection Reads navigator.language, validates against a 20-language whitelist; falls back to en if unsupported.
Runtime dictionary Creates/updates window._weshareLangMap in memory for translations; no cookies or identifiers.
Secure requests Fetches translation payload via CORS with credentials:'omit'; guarded by timeout/abort (resilient & ephemeral).
Graceful fallback On failure, uses safe defaults (e.g., \"Copy Link\", \"Share to any service\"), ensuring a usable UI.
Completion signal Sets _weshareTranslationComplete = true and dispatches weshareTranslationsComplete for the patch to hook into.

Runtime objects & structure

The loader exposes an in-memory map the patch can read safely at runtime:

json
{
  "lang": "es",
  "_weshareLangMap": {
    "share_any": "Compartir a cualquier servicio",
    "copy_link": "Copiar enlace",
    "email": "Correo",
    "thanks_message": "¡Gracias por compartir!"
  }
}

Listening for completion

The Language Patch waits for either the flag or the custom event before “painting” text/attributes (DOM-safe, non-destructive):

javascript
// Option A: event-driven
window.addEventListener('weshareTranslationsComplete', () => {
  applyLanguagePatch(window._weshareLangMap);
});

// Option B: flag fallback
if (window._weshareTranslationComplete) {
  applyLanguagePatch(window._weshareLangMap);
}

Secure, ephemeral fetch (with timeout)

Requests omit credentials and are time-boxed; on timeout or network errors, the loader falls back to defaults:

javascript
const ac = new AbortController();
const t = setTimeout(() => ac.abort(), 3500);

fetch('/api/weshare/lang?code=' + navigator.language, {
  method: 'GET',
  credentials: 'omit',
  mode: 'cors',
  signal: ac.signal
})
.then(r => r.ok ? r.json() : Promise.reject('bad status'))
.then(payload => {
  window._weshareLangMap = payload._weshareLangMap;
  window._weshareTranslationComplete = true;
  window.dispatchEvent(new Event('weshareTranslationsComplete'));
})
.catch(() => {
  window._weshareLangMap = {
    share_any: 'Share to any service',
    copy_link: 'Copy Link',
    email: 'Email',
    thanks_message: 'Thank you for sharing!'
  };
  window._weshareTranslationComplete = true;
  window.dispatchEvent(new Event('weshareTranslationsComplete'));
})
.finally(() => clearTimeout(t));

Optional analytics (privacy-safe)

If GA4 is present, you may log a language switch event without any identifiers:

javascript
gtag('event', 'weshare_language_switched', {
  lang: (window._weshareLangMap && window._weshareLangMap.lang) || 'en',
  ai_activated: true
});
What this proves: real-time, client-side language switching with explicit events/flags, no PII / no cookies, resilient fallbacks, and non-destructive DOM patching — a privacy-first AI layer that is safe to run on any page.

Language Patch (weshare-language-patch-ai.js)

What it does: Applies language overrides at render time — non-destructively.
Usage: Combine with the AI Language Loader for best results.
Privacy: No cookies / no PII; reads in-memory translations only.
AspectDetails
UI-key mapping Defines a langKeyMap for UI elements (e.g., copy, email, thanks, share) → maps keys to translation tokens.
Non-destructive patch Iterates only text nodes, preserves structure and children; also updates safe attributes (title, placeholder).
Special messages Targets .thanks-message for post-share UX messages.
Sync with Loader Waits for the Loader’s flag _weshareTranslationComplete or the custom event weshareTranslationsComplete (10s fallback).
Safe startup A MutationObserver ensures the share menu exists before patching to avoid DOM races.

UI-key mapping

Language Patch uses a simple map from UI keys to translation tokens, then resolves them against window._weshareLangMap prepared by the Loader.

javascript
const langKeyMap = {
  '.share-any'       : 'share_any',
  '.copy-link'       : 'copy_link',
  '.email-label'     : 'email',
  '.thanks-message'  : 'thanks_message'
};

Sync with the Loader (event or flag)

The patch waits for translations to be ready; it supports both event-driven and flag-based sync, plus a timed fallback:

javascript
function tryApply() {
  if (window._weshareTranslationComplete && window._weshareLangMap) {
    applyLanguagePatch(window._weshareLangMap);
    return true;
  }
  return false;
}

// A) Event-driven
window.addEventListener('weshareTranslationsComplete', () => tryApply());

// B) Flag fallback (+ timeout)
if (!tryApply()) {
  setTimeout(tryApply, 10000); // 10s fallback
}

Non-destructive text & attribute patching

The patch touches only text nodes and safe attributes, leaving DOM structure intact:

javascript
function applyLanguagePatch(dict) {
  // 1) Text nodes
  const walker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_TEXT,
    null,
    false
  );
  const replaceIfKeyed = (text) => {
    // Example: "{{copy_link}}" resolves via dict.copy_link
    const m = text.data.match(/{{\\s*([a-z0-9_]+)\\s*}}/i);
    if (m && dict[m[1]]) text.data = dict[m[1]];
  };
  for (let n = walker.currentNode; n; n = walker.nextNode()) replaceIfKeyed(n);

  // 2) Attributes (title/placeholder)
  document.querySelectorAll('[title],[placeholder]').forEach(el => {
    ['title','placeholder'].forEach(attr => {
      const val = el.getAttribute(attr);
      const m = val && val.match(/{{\\s*([a-z0-9_]+)\\s*}}/i);
      if (m && dict[m[1]]) el.setAttribute(attr, dict[m[1]]);
    });
  });

  // 3) Direct selectors (thanks-message, etc.)
  Object.entries({
    '.thanks-message': 'thanks_message'
  }).forEach(([sel,key]) => {
    const node = document.querySelector(sel);
    if (node && dict[key]) node.textContent = dict[key];
  });
}

Safe startup with MutationObserver

Ensure the share menu exists before patching; this avoids race conditions with late-rendered menus:

javascript
const observer = new MutationObserver(() => {
  const menu = document.querySelector('.weshare-menu'); // <-- update to your menu selector
  if (menu) {
    tryApply();
    observer.disconnect();
  }
});
observer.observe(document.documentElement, { childList: true, subtree: true });
What this proves: real-time, client-side language switching via explicit events/flags, fully privacy-safe (no cookies / no PII), and non-destructive DOM patching — a robust layer that plays nicely with any theme/CMS.

Post-Share Monetization

Turn every successful share into a privacy-first revenue & engagement moment — overlays, thank-you screens, rewarded actions, or smart redirects.

TL;DR for engineers
  • Runs client-side after a successful share event. No cookies, no PII, no profiling.
  • Configurable modes: overlay, inline, redirect, reward.
  • Plug in your ad unit (AdSense, direct, affiliate) or use a custom component.
  • Full control via window.e_mailit_config.post_share + lifecycle callbacks.
  • Emits GA4/GTM events: impression, click, close, reward_granted, error.

How it Works

  1. User clicks a WeShareAI share button and completes the share intent.
  2. WeShareAI fires a weshareai:share:complete event (no PII).
  3. If post_share.enabled is true, WeShareAI renders the selected post-share surface (overlay/inline/redirect) and mounts your monetization unit or message.
  4. Lifecycle events are dispatched to your listeners (analytics, rewards, A/B testing, throttling).

Quick Start

Enable the engine and choose a mode. The example below shows an overlay with a Google AdSense unit and a rewarded CTA.

javascript
// Base config (must exist before WeShareAI scripts)
window.e_mailit_config = {
  // ...your existing config...
  post_share: {
    enabled: true,
    mode: "overlay",           // "overlay" | "inline" | "redirect" | "reward"
    width: 420,
    height: 360,
    throttle: {                // show at most N times per visitor/session
      perSession: 3,           // client-side memory; no cookies
      minIntervalSec: 90
    },
    geoAllow: ["US","ES","BR","JP","PL"],    // optional allow/deny lists
    geoDeny: [],
    langAllow: ["en","es","pt","ja","pl"],   // optional language gating
    closeable: true,

    // Monetization unit (choose one strategy or mix via custom renderer)
    unit: {
      type: "adsense",         // "adsense" | "iframe" | "html" | "none"
      adsense: {
        client: "ca-pub-XXXXXXXXXXXXXXX",
        slot:   "1234567890",
        format: "rectangle"
      },
      iframe: {                // use for affiliate / SSP / direct deals
        src: "https://your-ad-or-offer.example.com/?pub=123",
        width: 300,
        height: 250,
        sandbox: "allow-scripts allow-same-origin"
      },
      html: {
        // simple markup for house ads or CTAs
        markup: "<div class='ps-cta'><h4>Thanks for sharing!</h4><p>Get 10% off your next purchase.</p><button data-ps-action='claim'>Claim Reward</button></div>"
      }
    },

    // Optional reward logic (client-side, tokenless)
    reward: {
      enabled: true,
      label: "Claim reward",
      verifyShare: true,        // lightweight, heuristic (no PII)
      callbackUrl: "/api/reward/claim" // your server validates & issues reward
    },

    // AI-assist knobs (contextual, non-identifying signals)
    ai: {
      languageSync: true,      // auto match overlay copy to UI language
      theme: "auto",           // "auto" adapts to site theme
      density: "compact"       // "cozy" | "compact"
    }
  }
};

Lifecycle & Events

Listen to WeShareAI’s custom events to track performance or trigger custom flows.

javascript
// 1) Share completed (always fires after a successful share)
window.addEventListener("weshareai:share:complete", (ev) => {
  // ev.detail: { network, lang, country, device, url }
  dataLayer.push({ event: "share_complete", ...ev.detail });
});

// 2) Post-share surface lifecycle
window.addEventListener("weshareai:postshare:impression", (ev) => {
  dataLayer.push({ event: "postshare_impression", surface: ev.detail.surface });
});

window.addEventListener("weshareai:postshare:click", (ev) => {
  dataLayer.push({ event: "postshare_click", target: ev.detail.target });
});

window.addEventListener("weshareai:postshare:close", () => {
  dataLayer.push({ event: "postshare_close" });
});

window.addEventListener("weshareai:postshare:reward_granted", (ev) => {
  // { token, rewardId } - issued by your backend; no PII in the client
  dataLayer.push({ event: "reward_granted", rewardId: ev.detail.rewardId });
});

window.addEventListener("weshareai:postshare:error", (ev) => {
  console.warn("Post-share error:", ev.detail);
  dataLayer.push({ event: "postshare_error", code: ev.detail.code });
});

Consent Gate (CMP / Consent Mode)

Render post-share ads/iframes only when ad consent is present. Below we show three patterns—choose the one that fits your site.

javascript
// Option A:
function hasAdConsentSync() {
  return window.__ad_consent_granted === true;
}

// Option B: IAB TCF v2 (async)
function hasAdConsentTCF() {
  return new Promise((resolve) => {
    if (typeof window.__tcfapi !== 'function') return resolve(false);
    window.__tcfapi('addEventListener', 2, (tcData, success) => {
      if (!success) return resolve(false);
      const ready = (tcData.eventStatus === 'tcloaded' || tcData.eventStatus === 'useractioncomplete');
      if (!ready) return resolve(false);
      
      const ok = tcData.purpose && tcData.purpose.consents && !!tcData.purpose.consents['1']; // Storage/Access
      resolve(!!ok);
    });
  });
}

// Option C: Google Consent Mode v2 via dataLayer
function hasAdConsentGCM() {
  if (!window.dataLayer) return false;
  const last = [...window.dataLayer].reverse().find(e => e.consent_update);
  return !!(last && last.ad_user_data === 'granted' && last.ad_personalization === 'granted');
}


window.addEventListener('weshareai:share:complete', async () => {
  const allow = hasAdConsentSync() || hasAdConsentGCM() || await hasAdConsentTCF();
  if (!allow) return; // block monetization surface
  // ...render post-share surface here...
});
Note: WeShareAI does not set cookies/IDs. The display of ad units always honors the site’s consent state.

Event Naming Map (DOM → GA4)

DOM EventPurposeSuggested GA4 event
weshareai:share:completeShare completeshare_complete
weshareai:postshare:impressionOverlay/Inline showpostshare_impression
weshareai:postshare:clickClick inside the unitpostshare_click
weshareai:postshare:closeClosepostshare_close
weshareai:postshare:errorError render/iframepostshare_error
weshareai:postshare:reward_grantedRewardreward_granted

The mapping is suggested; if you already have GA4 naming conventions, keep them for consistency.

Throttle (No Cookies)

Limits impression frequency at the sessionStorage level (not cookies/IDs):

javascript
const PFX = 'wsai_ps_';
function canShowPostShare({ perSession = 3, minIntervalSec = 90 } = {}) {
  try {
    const now = Date.now();
    const count = parseInt(sessionStorage.getItem(PFX + 'count') || '0', 10);
    const last  = parseInt(sessionStorage.getItem(PFX + 'last')  || '0', 10);
    if (count >= perSession) return false;
    if (now - last < (minIntervalSec * 1000)) return false;
    sessionStorage.setItem(PFX + 'count', String(count + 1));
    sessionStorage.setItem(PFX + 'last', String(now));
    return true;
  } catch { return true; } // if storage is disabled, allow showing once
}

// Sample:
window.addEventListener('weshareai:share:complete', () => {
  if (!canShowPostShare({ perSession: 3, minIntervalSec: 90 })) return;
  // render post-share here...
});

Throttling is client-side and does not require cookies/PII.

Accessibility (Overlay)

Use ARIA & focus-trap for accessibility:

html
<div id="ps-overlay" role="dialog" aria-modal="true" aria-labelledby="ps-title" hidden>
  <div class="ps-surface" tabindex="-1">
    <h2 id="ps-title">Thanks for sharing!</h2>
    <button type="button" class="ps-close" aria-label="Close">×</button>
    <div class="ps-content"><!-- ad / cta here --></div>
  </div>
</div>
javascript
// ESC close + focus trap + disable background scroll
(function(){
  const overlay = document.getElementById('ps-overlay');
  const surface = overlay && overlay.querySelector('.ps-surface');
  const closeBtn = overlay && overlay.querySelector('.ps-close');

  function openOverlay(){
    overlay.hidden = false;
    document.documentElement.style.overflow = 'hidden';
    surface.focus();
  }
  function closeOverlay(){
    overlay.hidden = true;
    document.documentElement.style.overflow = '';
  }

  // ESC
  document.addEventListener('keydown', (e) => {
    if (!overlay || overlay.hidden) return;
    if (e.key === 'Escape') closeOverlay();
  });

  // Click close
  closeBtn && closeBtn.addEventListener('click', closeOverlay);

  // Focus trap
  overlay.addEventListener('keydown', (e) => {
    if (e.key !== 'Tab') return;
    const focusables = overlay.querySelectorAll('a,button,input,textarea,select,[tabindex]:not([tabindex="-1"])');
    const first = focusables[0], last = focusables[focusables.length - 1];
    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
  });

  // Example usage: open after share (provided consent/throttle checks pass)
  // window.addEventListener('weshareai:postshare:impression', openOverlay);
})();
Tip: Set focus on the first interactive element, allow closing via ESC/Close, and prevent the page from scrolling behind when the overlay is open.
Mobile note: In some mobile share sheets (e.g., iOS), “share complete” is heuristic. If the user cancels, the post-share will not appear. Design your funnel with this in mind.
Security add-ons:
  • For external links inside the unit, use rel="noopener noreferrer".
  • For iframes, keep a strict sandbox (e.g., sandbox="allow-scripts allow-same-origin").
  • Do not pass emails, IDs, or other PII in URLs or payloads.

Inline & Redirect Modes

Inline mounts your unit inside a container you control. Redirect sends the user to a dedicated thank-you route you host.

html
<!-- Inline container -->
<div id="weshareai-postshare" style="min-height:260px"></div>
javascript
window.e_mailit_config = window.e_mailit_config || {};
window.e_mailit_config.post_share = {
  enabled: true,
  mode: "inline",
  container: "#weshareai-postshare",
  unit: { type: "html", html: { markup: "<div class='ps-inline-banner'>Thanks!</div>" } }
};

// Redirect mode
window.e_mailit_config.post_share = {
  enabled: true,
  mode: "redirect",
  redirectUrl: "/thank-you?src=weshareai" // your page can render any ad/offers
};

AdSense Integration Tips

  • Respect AdSense content & placement policies; avoid intrusive overlays on first paint.
  • Load AdSense once. For overlays, render the slot after the share event to avoid layout shifts.
  • Use data-ad-client / data-ad-slot on the mounted element and trigger (adsbygoogle = window.adsbygoogle || []).push({}) after injection.
javascript
// Hydrate an AdSense slot inside the overlay
window.addEventListener("weshareai:postshare:impression", () => {
  const el = document.querySelector(".ps-adsense-slot");
  if (el && window.adsbygoogle) {
    try { (adsbygoogle = window.adsbygoogle || []).push({}); } catch(e){}
  }
});

Rewarded Share (Optional)

Offer a coupon, credit, or content unlock after verified share completion. Verification is heuristics-based (no PII). Final issuance happens on your server.

javascript
// Client: request a reward after share
document.addEventListener("click", async (e) => {
  if (e.target.matches("[data-ps-action='claim']")) {
    const res = await fetch("/api/reward/claim", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ source: "weshareai", intent: "share" })
    });
    const out = await res.json();
    if (out.granted) {
      window.dispatchEvent(new CustomEvent("weshareai:postshare:reward_granted", {
        detail: { rewardId: out.rewardId }
      }));
    }
  }
});

AI Assist (Language & Layout)

When ai.languageSync is on, the surface text mirrors the user’s UI language (from WeShareAI Language AI). You can override copy by language:

javascript
window.e_mailit_config.post_share.i18n = {
  "en": { title: "Thanks for sharing!", cta: "View offer" },
  "es": { title: "¡Gracias por compartir!", cta: "Ver oferta" },
  "pt": { title: "Obrigado por compartilhar!", cta: "Ver oferta" },
  "ja": { title: "共有ありがとう!", cta: "オファーを見る" }
};
Privacy & Compliance
  • No cookies, no PII, no cross-site identifiers.
  • Client-side only; ephemeral signals (language, coarse geo, device) for contextual rendering.
  • Compatible with GDPR/CCPA and consent layers (CMP). Honors your site’s consent state.
  • Server endpoints you build for rewards must also avoid PII unless you have explicit consent.

A/B Testing & Tuning

Use your own split logic to compare mode, unit types, or copy. Push results to GA4 or your analytics.

javascript
// Minimal experiment toggle
const variant = Math.random() < 0.5 ? "overlay" : "inline";
window.e_mailit_config.post_share = {
  enabled: true,
  mode: variant,
  unit: { type:"html", html:{ markup:"<div>TY!</div>" } }
};
dataLayer.push({ event: "ps_experiment_assign", variant });

Supported Surfaces & Units

Surface Best for Units Notes
overlay High visibility after share AdSense, iframe, HTML Closeable; throttle recommended
inline Native embed inside article AdSense, HTML Mount via container
redirect Custom thank-you routes Any (your page) Use for long-form offers
reward Coupons / unlocks HTML + backend Heuristic verify; finalize server-side
Security Notes
  • For third-party iframes, use a restrictive sandbox attribute.
  • Avoid inlining untrusted HTML. Prefer vetted templates or server-generated markup.
  • Do not pass emails, user IDs, or other PII in URLs or payloads.

Need more control? See the weshareai:postshare:* event payloads in the console, or contact us for enterprise hooks.

AI Signals

Contextual, non-identifying inputs that let WeShareAI adapt the share UX in real time — with no cookies and no PII.

TL;DR for engineers
WeShareAI reads browser language and a coarse country signal, then applies curated mappings to pick the right networks and labels. It emits optional, privacy-safe GA4 events (e.g. ai_replace_observer) for measurement. Language translations are fetched via ephemeral requests and patched into the DOM non-destructively. No identifiers are stored or exchanged.

Signal Catalog

SignalSourceUsed byExampleRetention
Country (coarse) Server endpoint /api/get-country.php with US fallback on error Smart Share Buttons (network selection) cc = "GR" → prioritize Viber, Messenger, WhatsApp Not stored by WeShareAI; may be logged as anonymous GA4 event metadata
Browser language navigator.language → validated against a 20-language whitelist → fallback en Language Loader & Patch (UI labels/tooltips) es-ES → “Compartir a cualquier servicio” In-memory map only (window._weshareLangMap)
Selected services Platform mapping servicesByCountry at runtime Renderer (e_mailit.parseButtons()) ["Facebook","Viber","WhatsApp", …] Not persisted; optionally sent as GA4 event field (selected_services)
AI activation Runtime when AI replacement occurs Analytics ai_activated: true (GA4) Anonymous event only
Translation readiness Flag + custom event Language Patch _weshareTranslationComplete = true & weshareTranslationsComplete Ephemeral (page lifetime)

How Signals Drive Decisions

  1. Detect: On page load, WeShareAI requests the visitor’s country (coarse) and reads browser language from the client.
  2. Select: It looks up a servicesByCountry map and assembles the most relevant share networks for that market.
  3. Render: AI placeholders (.e-mailit_btn_AI) are replaced with the selected networks and passed to e_mailit.parseButtons().
  4. Localize: Language Loader fetches translations via CORS with credentials:'omit' (timeout-guarded), then signals completion; Language Patch updates text/attributes without breaking the DOM.
  5. Measure (optional): If GA4 is present, WeShareAI emits an anonymous event noting that AI logic ran and which services were shown.

Example: Country → Networks

javascript
// Excerpt (platform-managed)
const servicesByCountry = {
  GR: ["Facebook","Messenger","Viber","WhatsApp","Gmail","Telegram","SMS","Twitter"],
  JP: ["LINE","Twitter","Facebook","Gmail","Hatena","WhatsApp","Messenger","Telegram","SMS","Pinterest"],
  US: ["Facebook","Twitter","Pinterest","LinkedIn","WhatsApp","Messenger","Telegram","Reddit","Gmail","SMS"]
};

Optional Analytics (GA4)

Privacy-safe; no identifiers. Emitted only if gtag exists.

javascript
gtag('event', 'ai_replace_observer', {
  event_category: 'WeShare AI',
  country: cc,                    // e.g., "GR"
  ai_activated: true,
  selected_services: services.join(','),
  page_url: window.location.href,
  timestamp: new Date().toISOString()
});

Language Flow (Loader → Patch)

javascript
// Loader: pick active language (20-lang whitelist), fetch translations (CORS, credentials:'omit', timeout)
const lang = navigator.language.slice(0,2) || 'en';
const supported = ["ja","en","it","es","el","hi","pl","zh","fr","de","ko","pt","ru","ar","nl","vi","et","th","cs","da"];
const active = supported.includes(lang) ? lang : 'en';
// ... after fetching keys:
window._weshareLangMap = { /* in-memory translations */ };
window._weshareTranslationComplete = true;
window.dispatchEvent(new CustomEvent('weshareTranslationsComplete'));

// Patch: wait for event/flag, then translate text nodes + safe attributes (title/placeholder)
window.addEventListener('weshareTranslationsComplete', () => applyLanguagePatch());
setTimeout(() => { if (!window._weshareTranslationComplete) applyLanguagePatch(); }, 10000);
Resilience & Fallbacks
  • Country: If the endpoint fails, WeShareAI falls back to "US" so rendering is never blocked.
  • Translations: If API calls time out or fail, safe defaults are used (e.g., “Copy Link”, “Share to any service”).
  • Patch Sync: If no completion event arrives, the patch applies after a 10s timeout.
Privacy by design
  • No cookies, no cross-site IDs, no user profiling.
  • Language translations are ephemeral (in-memory map); requests omit credentials.
  • Analytics are optional and aggregate (e.g., which services were rendered in a country).
code
// Possible events
'weshareai:share_render'   // buttons rendered
'weshareai:share_open'     // a share tray opened
'weshareai:share_complete' // a share action completed
'weshareai:lang_applied'   // language patch applied

Naming may vary by build; check release notes for the exact event list you’re shipping.

Ranking (how WeShareAI chooses & orders networks)

TL;DR: Ranking is deterministic and contextual. At runtime we detect the visitor’s country, pick the country’s preset from servicesByCountry, optionally trim to a max, inject the corresponding .e-mailit_btn_{service} nodes, and hand off to the core renderer. Telemetry confirms what was shown — all without cookies or PII.
InputRole in RankingNotes
Country Primary selector Resolved via a lightweight endpoint; falls back to US if unavailable.
Browser language UI labels (not order) Used by Language AI for copy/labels; does not change button order today.
Device / viewport Layout density Impacts layout density and visibility caps; order remains country-driven.
Page context Light heuristics Reserved for future refinements; base order is still from presets.

Country presets

A curated servicesByCountry map encodes the preferred order per market. This gives a strong default that is easy to audit and evolve over time.

json
{
  "GR": ["Facebook","Messenger","Viber","WhatsApp","Gmail","Telegram","SMS","Twitter"],
  "US": ["Facebook","Twitter","Pinterest","LinkedIn","WhatsApp","Messenger","Telegram","Reddit","Gmail","SMS"],
  "JP": ["LINE","Twitter","Facebook","Gmail","Hatena","WhatsApp","Messenger","Telegram","SMS","Pinterest"]
  // ...more countries
}

Runtime selection flow

  1. Detect placeholders: A MutationObserver watches for .e-mailit_btn_AI in toolboxes.
  2. Resolve country: Fetch a coarse country code (e.g., /api/get-country.php); if it fails, use US.
  3. Select list: Read the array from servicesByCountry[country] (or US as fallback).
  4. Apply cap: Respect an optional data-max on the placeholder to keep the set compact (e.g., 4–6 buttons).
  5. Inject & render: Replace the AI placeholder with .e-mailit_btn_{service} nodes, then call e_mailit.parseButtons().
  6. Log telemetry: Emit a GA4 event including country, selected_services, and ai_activated:true.
html
<!-- Publisher theme markup -->
<div class="e-mailit_toolbox">
  <div class="e-mailit_btn_AI" data-max="6"></div>
</div>
javascript
// Minimal, framework-agnostic sketch of the live logic
async function chooseAndRender() {
  const country = await getCountryOrUS();           // e.g., "/api/get-country.php" → "GR" | fallback "US"
  const preset  = servicesByCountry[country] || servicesByCountry.US;
  document.querySelectorAll('.e-mailit_btn_AI').forEach(el => {
    const max = Number(el.dataset.max || preset.length);
    el.innerHTML = "";                               // clean slate
    preset.slice(0, max).forEach(svc => {
      const btn = document.createElement("div");
      btn.className = "e-mailit_btn_" + svc;
      btn.setAttribute("data-ai", "true");
      el.appendChild(btn);
    });
  });
  e_mailit.parseButtons();                           // hand off to the core renderer
  gtag('event', 'weshare_ai_render', {
    ai_activated: true,
    country,
    selected_services: (preset || []).join(',')
  });
}

Why this approach?

  • Predictable & auditable: Presets make changes explicit and reviewable.
  • Fast client runtime: No heavy models on the page; sub-ms list selection.
  • Privacy-first: No cookies, IDs, or cross-site profiling — just ephemeral context.
  • Easy to evolve: Presets can be re-weighted centrally as aggregate CTR trends shift.
What this proves: country-aware ordering, deterministic runtime replacement, and transparent analytics confirming the exact services rendered — with graceful fallbacks if a signal is missing.

Notes: Language AI localizes labels but does not change order today. Future versions may incorporate device or content heuristics into ranking; the current behavior remains country-preset driven for predictability.

Fallbacks

WeShareAI is designed to be resilient-by-default: the share UI must never break, even if a network call fails, a signal is missing, or analytics are disabled. All fallbacks are privacy-preserving (no cookies/PII) and deterministic.

TL;DR: If a signal isn’t available, WeShareAI uses sensible defaults and still renders the buttons. Language falls back to safe strings. Analytics are optional no-ops. The patch applies after a timeout if the event never arrives.

Failure Modes & Automatic Fallbacks

Component Failure / Trigger Automatic Fallback User Impact Dev Hooks
Country detection Endpoint error / timeout Use "US" as default country; pick servicesByCountry.US Buttons still render (US preset) getCountryOrUS() pattern; log GA4 with country:"US"
Services preset Unknown country / empty mapping Fall back to a core default set of popular services Compact, usable set Respect data-max on placeholders
Language Loader Unsupported language / fetch failed / timeout Set activeLang="en"; use safe defaults (e.g., “Copy Link”, “Share to any service”) English labels; fully functional UI Still set _weshareTranslationComplete=true and dispatch weshareTranslationsComplete
Language Patch No completion event received Apply after 10s timeout with whatever map is available; otherwise no-op UI stays in default language Event-based and timeout-based sync supported
Renderer Dynamic DOM / late toolboxes MutationObserver waits; re-runs deterministically Buttons appear when container is ready Idempotent replacement; no double-inserts
Analytics (GA4) gtag missing / consent denied Skip events silently (no effect on UX) No analytics; UX intact Guard calls with if(window.gtag); honor site consent

Guarded fetch with timeout (country or translations)

javascript
async function fetchWithTimeout(url, ms = 3500, opts = {}) {
  const ac = new AbortController();
  const id = setTimeout(() => ac.abort(), ms);
  try {
    const res = await fetch(url, { ...opts, signal: ac.signal, credentials: 'omit', mode: 'cors' });
    if (!res.ok) throw new Error('bad status');
    return await res.json();
  } finally { clearTimeout(id); }
}

// Country fallback
async function getCountryOrUS() {
  try {
    const out = await fetchWithTimeout('/api/get-country.php');
    return (out && out.cc) || 'US';
  } catch { return 'US'; }
}

// Translations fallback (event/flag always emitted)
async function getTranslationsOrDefault(lang) {
  try {
    const payload = await fetchWithTimeout('/api/weshare/lang?code=' + lang);
    window._weshareLangMap = payload._weshareLangMap;
  } catch {
    window._weshareLangMap = {
      share_any: 'Share to any service',
      copy_link: 'Copy Link',
      email: 'Email',
      thanks_message: 'Thank you for sharing!'
    };
  } finally {
    window._weshareTranslationComplete = true;
    window.dispatchEvent(new Event('weshareTranslationsComplete'));
  }
}

Placeholder rendering (always produce buttons)

Even if signals are missing, WeShareAI injects a compact default list and hands off to the core renderer.

javascript
function renderServices(preset) {
  const fallback = ['Facebook','Twitter','WhatsApp','Messenger','Gmail']; // core default
  const list = (preset && preset.length) ? preset : fallback;

  document.querySelectorAll('.e-mailit_btn_AI').forEach(el => {
    const max = Number(el.dataset.max || list.length);
    el.innerHTML = '';
    list.slice(0, max).forEach(svc => {
      const n = document.createElement('div');
      n.className = 'e-mailit_btn_' + svc;
      el.appendChild(n);
    });
  });

  try { e_mailit.parseButtons(); } catch (e) { /* no-op: keep static */ }
}

Patch sync (event & timeout)

The Language Patch applies when translations are ready — or after a safe timeout if they aren’t.

javascript
function tryApplyPatch() {
  if (window._weshareTranslationComplete && window._weshareLangMap) {
    applyLanguagePatch(window._weshareLangMap);
    return true;
  }
  return false;
}

window.addEventListener('weshareTranslationsComplete', () => tryApplyPatch());
setTimeout(() => { tryApplyPatch(); }, 10000); // 10s fallback

Telemetry is optional (safe no-ops)

Analytics never block rendering. GA4 calls are guarded and skipped if the site has no consent or gtag is not present.

javascript
function logAIShown(country, services) {
  if (!window.gtag) return;              // no analytics: do nothing
  try {
    gtag('event', 'weshare_ai_render', {
      ai_activated: true,
      country,
      selected_services: services.join(',')
    });
  } catch { /* no-op */ }
}
What this proves: The system degrades gracefully under network failures, missing signals, or disabled analytics; the share experience always renders, language is safe, and privacy promises (no cookies/PII) hold under all fallbacks.

Notes: Fallbacks are deterministic and testable. To simulate: block the country endpoint, force an unsupported language, remove gtag, or delay the toolbox node — the UI should still render and remain usable.

AI Events & Analytics

Privacy-first instrumentation for visibility and tuning. WeShareAI never sets cookies/IDs; events are optional, consent-aware, and carry only non-identifying context (e.g., country code, rendered services).

TL;DR — Two layers:
  • DOM events you can listen to in the page (lifecycle, language readiness, post-share).
  • GA4 events (guarded) for aggregate insights — no PII, no profiling. If gtag or consent is missing, calls are skipped.

Event Namespaces

NamespaceExamplesPurpose
DOM weshareTranslationsComplete, weshareai:share:complete, weshareai:postshare:impression|click|close|reward_granted|error Listen from your code for language readiness, share completion & post-share lifecycle.
GA4 ai_replace_observer, weshare_ai_render, weshare_ai_click, weshare_language_switched, postshare_* Anonymous, aggregate analytics for ranking efficacy & UX tuning.

DOM Events (listen in your app)

EventWhen it firesSample payload
weshareTranslationsComplete Language Loader finished (even on fallback) { translations: window._weshareLangMap }
weshareai:share:complete After a successful share intent { network, lang, country, device, url }
weshareai:postshare:impression|click|close|reward_granted|error Post-share surface lifecycle { surface, target?, rewardId?, code? }
javascript
// Language ready
window.addEventListener('weshareTranslationsComplete', (ev) => {
  // use window._weshareLangMap safely
});

// Share completed
window.addEventListener('weshareai:share:complete', (ev) => {
  // ev.detail = { network, lang, country, device, url }
});

// Post-share lifecycle
['impression','click','close','reward_granted','error'].forEach(type => {
  window.addEventListener('weshareai:postshare:' + type, (ev) => {
    // react / push to dataLayer
  });
});

GA4 Events (optional, consent-aware)

Guard all calls; skip if no consent or gtag is undefined.

EventFiresPayload (suggested)
ai_replace_observer When AI replacement/render runs { country, ai_activated:true, selected_services, page_url, timestamp }
weshare_ai_render Alternative name for “rendered” (keep your naming conventions) { country, ai_activated:true, selected_services }
weshare_ai_click On share button click { service, ai_activated:true }
weshare_language_switched Language layer changed labels { lang, ai_activated:true }
postshare_impression|click|close|reward_granted|error Post-share surface lifecycle { surface, target?, rewardId?, code? }
javascript
// Guarded GA4 helper (consent-aware)
function logEvent(name, params) {
  if (!window.gtag) return; // no analytics: skip
  try { gtag('event', name, params); } catch {}
}

// Rendered (country-level)
logEvent('ai_replace_observer', {
  country: cc,                         // "GR", "US", ...
  ai_activated: true,
  selected_services: services.join(','),
  page_url: window.location.href,
  timestamp: new Date().toISOString()
});

// Click
document.addEventListener('click', (e) => {
  const btn = e.target.closest('[class^="e-mailit_btn_"]');
  if (!btn) return;
  const svc = Array.from(btn.classList).find(c => c.startsWith('e-mailit_btn_')).replace('e-mailit_btn_', '');
  logEvent('weshare_ai_click', { service: svc, ai_activated: true });
});

// Language switched (optional)
logEvent('weshare_language_switched', {
  lang: (window._weshareLangMap && window._weshareLangMap.lang) || 'en',
  ai_activated: true
});

Consent Pattern

Honor your CMP/Consent Mode and skip analytics when consent is absent.

javascript
function hasAnalyticsConsent() {
  // Example: consult your CMP / Consent Mode state here
  return window.__analytics_consent__ === true;
}
function logEventConsentSafe(name, params) {
  if (!hasAnalyticsConsent() || !window.gtag) return;
  gtag('event', name, params);
}

Cheatsheet: DOM → GA4

DOM EventSuggested GA4Why
weshareTranslationsCompleteweshare_language_switchedLanguage layer ready (optional log)
weshareai:share:completeshare_complete (custom)Measure successful share intents
weshareai:postshare:impressionpostshare_impressionPost-share surface shown
weshareai:postshare:clickpostshare_clickEngagement inside surface
weshareai:postshare:closepostshare_closeDismissal
weshareai:postshare:reward_grantedreward_grantedCoupon/credit issuance (no PII)
weshareai:postshare:errorpostshare_errorDiagnostics

Debugging

Enable the console to see internal traces. Look for [AI] lines during smart rendering and [Patch] lines during language patch.

What this proves: Transparent, privacy-safe analytics that confirm when AI ran and what it rendered — with clean opt-outs when consent or analytics are absent.

Privacy

WeShareAI is built privacy-first: no cookies, no cross-site IDs, no per-user profiling. The runtime uses only contextual, non-identifying signals (country code, browser language, device/context) to adapt the share UI. Optional analytics are consent-aware and aggregate-only.

TL;DR: No PII. No cookies. No self-modifying JS. Config-based updates only. Country & language are used at runtime, translations live in memory, and analytics (if enabled) are aggregate and consent-gated.

What We Process (and where)

Category Examples Where processed Storage Purpose
Contextual signals country (ISO) browser language device/layout page context Client (JS). Country may be resolved via a lightweight endpoint. Ephemeral (page runtime only) Pick relevant networks, set labels/localization, layout density.
Translations window._weshareLangMap keys (UI labels/tooltips) Fetched via CORS (credentials:'omit'), applied by Patch In-memory only (no cookies/IDs) Localize UI safely; graceful defaults if fetch fails.
AI telemetry (optional) weshare_ai_render ai_replace_observer weshare_ai_click weshare_language_switched postshare_* GA4 (publisher’s property), consent-aware Aggregate by GA4; WeShareAI does not keep user-level logs Measure what rendered/was clicked to refine presets system-wide.
Throttling client-side impression caps Client (e.g., sessionStorage) No cookies / No IDs Prevent spammy UX without tracking users.

Consent & Compliance

  • No cookies set by WeShareAI. Any cookies present belong to your stack (e.g., GA4/CMP) and honor your CMP/Consent Mode.
  • Consent-aware analytics. GA4 calls are guarded; if consent is absent or gtag is missing, events are skipped.
  • Country-only resolution. The runtime uses just a country code. IP addresses are not handled by WeShareAI logic, and we do not profile users.
  • GDPR/CCPA-friendly by design. Contextual inputs only, no PII, no cross-site identifiers, no per-user learning.
javascript
// Guarded GA4 helper (consent-aware): do nothing if consent is absent
function hasAnalyticsConsent() {
  // consult your CMP / Consent Mode state here
  return window.__analytics_consent__ === true;
}
function logEvent(name, params) {
  if (!hasAnalyticsConsent() || !window.gtag) return;
  try { gtag('event', name, params); } catch {}
}

Network Requests (safe by default)

Language fetches omit credentials and are time-boxed; on failure, the UI falls back to safe defaults.

javascript
const ac = new AbortController();
const t = setTimeout(() => ac.abort(), 3500);
fetch('/api/weshare/lang?code=' + navigator.language, {
  method: 'GET',
  mode: 'cors',
  credentials: 'omit',   // no cookies/IDs sent
  signal: ac.signal
})
.then(r => r.ok ? r.json() : Promise.reject('bad status'))
.then(payload => {
  window._weshareLangMap = payload._weshareLangMap;
})
.catch(() => {
  // graceful defaults (no PII)
  window._weshareLangMap = {
    share_any: 'Share to any service',
    copy_link: 'Copy Link',
    email: 'Email',
    thanks_message: 'Thank you for sharing!'
  };
})
.finally(() => {
  window._weshareTranslationComplete = true;
  window.dispatchEvent(new Event('weshareTranslationsComplete'));
  clearTimeout(t);
});

Retention

  • WeShareAI: No user-level data lake. The runtime is stateless; translations live in memory only.
  • Server logs: Keep minimal infra logs only as needed for reliability/security; target ≤ 30 days max, with aggregate reporting.
  • GA4: Retention and settings are controlled by the publisher. Recommended: minimal retention, Google Signals off, no user ID, no PII fields.

Security Notes

  • Do not pass emails/IDs/PII in URLs or payloads.
  • For third-party iframes in post-share, use a restrictive sandbox and rel="noopener noreferrer" on links.
  • Prefer server-generated HTML over untrusted inline markup for monetization units.
Bottom line: WeShareAI adapts with context, not identities. No cookies, no cross-site tracking, no per-user ML. Analytics are optional and consent-aware, and all fallbacks preserve privacy guarantees.

Implementation note: The JS never rewrites itself. Improvements ship as config/rule updates at the platform level and are consumed by the same runtime script.

Data & Retention

WeShareAI follows a privacy-first lifecycle: no cookies, no IDs, and no per-user history. Runtime logic uses contextual, non-identifying inputs; translations live in memory; analytics (if enabled) are consent-aware and aggregate. Infrastructure logs rotate on short schedules, and there is no raw user-level data lake.

TL;DR: No PII stored. No cookies set. Context-only processing at runtime. Optional GA4 is aggregate & consent-gated. Infrastructure logs target ≤ 30 days. Rules/configs evolve at the platform level, not per user.

Data Inventory (What exists, where, and why)

Category Examples Source Stored by WeShareAI? Retention Purpose
Contextual signals country (ISO) browser language device/viewport page context Client (JS) and a lightweight country endpoint (returns ISO code only) No Ephemeral (page runtime) Choose relevant networks; localize labels; set layout density.
Translations window._weshareLangMap (UI labels/tooltips) Fetched via CORS with credentials:'omit' No (in-memory only) Ephemeral (page runtime) Localize UI safely; graceful defaults on failure.
AI telemetry (optional) weshare_ai_render ai_replace_observer weshare_ai_click weshare_language_switched postshare_* Publisher’s GA4 (consent-aware) No Per publisher GA4 policy Aggregate insights (what rendered/was clicked) for system-level tuning.
Throttling counters Impression limits Client (sessionStorage) No Session lifetime Prevent spammy UX without tracking users or setting cookies.
Infra logs Minimal access/error logs Platform infrastructure N/A (infra only) ≤ 30 days (rotation) Reliability & security (aggregate reporting only).

Retention Policy

Component Data Default Retention Notes
Runtime (client) Contextual signals; _weshareLangMap Ephemeral (page runtime) Nothing persisted by WeShareAI; no cookies/IDs.
Country resolver ISO country code only Ephemeral (response only) No IP stored by WeShareAI logic; fallback to US on failure.
Translations API Key/value label payload Ephemeral Delivered to the browser with credentials:'omit'; applied by Patch.
GA4 (optional) Anonymous events Per publisher setting Recommend minimal retention, no user_id, Google Signals off, no PII fields.
Server/infra logs Access/error logs ≤ 30 days Rotation policy; aggregate reporting only.

Consent & Controls

  • WeShareAI sets no cookies. Any cookies present belong to your stack (e.g., GA4/CMP) and follow your CMP/Consent Mode.
  • Analytics are optional & consent-aware. If consent is missing or gtag is undefined, events are skipped.
  • Country-only signal. The runtime uses a country code. There is no per-user profiling.
javascript
// Consent-aware analytics helper (no PII)
function hasAnalyticsConsent() {
  // Consult your CMP / Consent Mode
  return window.__analytics_consent__ === true;
}
function sanitizeEventParams(obj) {
  // Defensive: strip accidental PII-like fields
  const disallow = ['email','user_id','uid','phone','name','address'];
  const out = {};
  Object.keys(obj || {}).forEach(k => {
    if (disallow.includes(k.toLowerCase())) return;
    out[k] = String(obj[k]).slice(0, 512); // clamp length
  });
  return out;
}
function logEventSafe(name, params) {
  if (!hasAnalyticsConsent() || !window.gtag) return;
  try { gtag('event', name, sanitizeEventParams(params)); } catch {}
}

Data Lake & Exports

WeShareAI maintains no raw user-level data lake. If a future aggregate store is introduced (e.g., BigQuery/Snowflake), it will contain only anonymized, aggregated patterns for system-level tuning — never per-user histories.

DSR (Data Subject Requests)

Since WeShareAI does not store personal data, there is no per-user record to erase or export. GA4 events (if enabled) are owned by the publisher and subject to the publisher’s DSR workflows and retention settings.

Bottom line: WeShareAI adapts at the system level without collecting or storing personal data. Runtime signals are ephemeral, analytics are optional and consent-gated, and infrastructure logs rotate quickly (≤ 30 days).

Implementation note: Updates ship as config/rule changes consumed by the same JS runtime; there is no self-modifying code and no hidden state.

FAQ (AI only)

Q1: How does the AI in Smart Share Buttons work?

Our AI analyzes real-time contextual signals such as country, browser language, device, and engagement patterns. Based on these signals, it dynamically selects the most relevant social networks for each unique visitor. No two users necessarily see the same buttons — maximizing share rates and engagement without storing personal data.

Q2: How does the AI Language Switching work?

WeShareAI automatically detects each visitor’s browser language and geolocation. It then adapts the interface — including tooltips, share prompts, and custom messages — into the correct language in real time. If no match is found, it falls back to a default (English). This ensures a familiar and frictionless sharing experience for global audiences.

Q3: How do Smart Share Buttons and Language Switching work together?

Smart Share Buttons decide which social networks each user sees. Language Switching decides in which language the interface is displayed. Together, they create a two-layer personalization: what you see + how you see it. The result is more shares, more traffic, and more revenue — all while protecting user privacy.

Q4: Is this privacy-compliant?

Yes. WeShareAI is 100% GDPR-compliant and privacy-first. We do not collect Personally Identifiable Information (PII), do not use cookies, and do not profile users. All AI decisions are made contextually in real time, with anonymized signals only.

Q5: Can we say that the longer our AI is installed on websites, the smarter it becomes — even though we do not collect personal data or process it with machine learning?

The WeShareAI model has been trained on global behavioral patterns and operates contextually in real time. While WeShareAI does not collect or profile personal data, the system continuously improves at the platform level. With anonymized, aggregate engagement signals from thousands of sites, it refines its rules, mappings, and weightings — meaning accuracy and relevance steadily improve at a system-wide scale, not at the level of an individual site or user. No profiling or data harvesting takes place, and no machine learning is performed on personal data. The longer it runs across publishers, the more accurate and effective it becomes for everyone.

Q6: How does WeShareAI improve its intelligence and rules at the platform level? Does the AI write new code directly into the JavaScript?

No, the JavaScript does not rewrite itself. Improvements happen entirely at the platform level and are delivered to the runtime via updated configs (and sometimes through versioned script updates). The process works in three ways: First, through rule-based refinement, where smart-weshare-ai.js ships with sensible defaults (for example, top social networks per country), and we centrally adjust mappings or weights; publishers automatically receive the latest version without reinstalling anything. Second, through aggregate pattern learning, where we collect anonymized, aggregate engagement signals such as which button was clicked, from which country, and in which language. There is no PII and no user profiling. AI/ML models analyze these trends (for example, “LINE usage rising in Japan” or “WhatsApp trending in Poland”) and propose updated weightings and mappings, which we then apply at the system level, not per individual user. Third, the updates reach end users because the same JavaScript runs for all publishers, but it simply loads the dynamic settings we serve; the code doesn’t “write new code,” it just runs with improved configs informed by platform-level learning.

As for signals today, we rely on Google Analytics 4 events (e.g., weshare_ai_clicked, weshare_language_switched) for anonymous, event-level telemetry. We do not maintain our own raw-event data lake at this time — GA4 is our storage and analytics layer. This design choice keeps us privacy-compliant by default, with no PII, no user-level profiles, and no heavy infrastructure. Looking ahead, we may introduce a lightweight store (such as BigQuery or Snowflake) but only for aggregate patterns without user-level granularity, which would allow us to refresh rules even more precisely while maintaining the same privacy guarantees.

Bottom line: WeShareAI becomes smarter at a system-wide level through anonymized, aggregate signals and centralized rule updates. The JavaScript runtime simply consumes improved configs — it never generates or modifies its own code.

Q7: In what way does the WeShareAI system propose improved rules and mappings over time?

WeShareAI does not perform machine learning on raw user data, since we do not store or process PII. Instead, the system works with contextual signals and aggregate patterns collected via Google Analytics 4 events. The current logic is rules-based: we collect signals such as country-level share volumes, which networks receive the most clicks, and which languages correlate with higher share completion. From these we extract patterns — for example, “In Japan, LINE generates 4x more shares than Twitter” or “Visitors with browser language = Spanish share more frequently on WhatsApp.” Based on such insights, platform-wide priority lists are refined (e.g., top 10 networks per country, language-to-label mappings). The AI “learns” at the platform level, not per user, essentially updating the mappings and weights that smart-weshare-ai.js reads.

Looking ahead, the future logic will be semi-automated: aggregate exports from GA4/BigQuery can feed lightweight ML models (e.g., frequency ranking, uplift analysis). The AI will detect CTR changes and propose new rules such as “Promote TikTok to position #3 in Germany — CTR +12%” or “Add Viber to the Top 5 in Greece — usage trend is steadily increasing.” Human review will always remain part of the process, as we confirm before a production update goes live.

Key point: The AI does not rewrite JavaScript code. Instead, it updates rulesets and config tables that the JavaScript runtime consumes. All intelligence happens at the system level using anonymized aggregates, never at the individual user level. This means the share button gets smarter over time — without profiling or tracking.

Q8: What do we mean by “AI signals” in WeShareAI today, and why do we position the system as AI-powered instead of just static rules?

Today, WeShareAI operates as a rules-based contextual AI. While we do not run full machine learning pipelines on raw user data, the system already leverages a variety of AI-like signals that enable continuous adaptation: geography (IP → country) to adjust the top 10 networks per market, browser language for dynamic language switching, device type to prioritize networks differently (e.g., Viber/WhatsApp on mobile), content context to recognize categories like news, sports, or recipes, and aggregate CTR data from GA4 to promote the networks that actually receive clicks.

This approach makes the platform adaptive rather than static. Users in different regions and devices see different sets of buttons. Configurations are continuously updated — for example, when a network gains traction such as TikTok in Poland, the rulesets adjust automatically and all publishers benefit instantly. The intelligence resides in the central JS module, not hardcoded in each publisher’s site, so improvements roll out seamlessly without any re-installation.

From a UX and systems perspective, this already qualifies as AI-powered personalization, because the platform continuously adapts to contextual signals and engagement trends. Competitors like ShareThis or AddToAny remain static, while WeShareAI delivers dynamic, context-aware rendering. Looking ahead, the architecture is AI-ready: it is modular and designed so that real ML models (e.g., share prediction, translation quality optimization) can be plugged in without requiring changes from publishers.

In short: Today = rule-based contextual AI. Tomorrow = ML-driven AI. Either way, it is already smarter than legacy static share buttons.

Q9: How do the modules work together?

When a visitor lands on a page, the Smart Share script detects the visitor’s country and determines the most relevant set of networks based on geo/context presets. The UI then dynamically creates the appropriate buttons and passes them through the existing renderer. In parallel, the AI Language Loader translates labels via secure, ephemeral fetches and signals completion with a flag/event. The Language Patch waits for this signal and then carefully updates only the text and attributes without breaking the DOM. Meanwhile, the system records privacy-safe telemetry — logging the AI activation event and which services were displayed for optimization.

How it works (under the hood): WeShareAI detects country context at runtime and swaps in the most relevant share services, then renders the buttons and emits a privacy-safe analytics event (no PII). At the same time, the AI Language layer fetches ephemeral translations (credentials omitted, time-boxed) and signals completion; a DOM-safe patch updates only text nodes and attributes like title/placeholder, preserving structure. The result is a real-time, geo- and language-aware share UX that is fully GDPR-compliant.

Q10: Why do different users see different buttons?

Because WeShareAI adapts in real time to context. The system detects a visitor’s country, browser language, device type, and engagement trends, then dynamically prioritizes the most relevant social networks. This ensures that users in Japan may see LINE or Twitter first, while users in Greece may see Viber, and Spanish-language visitors may see WhatsApp — making sharing more intuitive and effective everywhere.

Q11: How does it choose networks?

WeShareAI selects networks using a combination of contextual rules and aggregate engagement data. At runtime, it detects the visitor’s country and device type, then pulls from a curated mapping of the most popular networks in that region (for example, LINE in Japan or Viber in Greece). It also checks the visitor’s browser language, ensuring that labels and defaults are localized. Over time, aggregate CTR signals from thousands of sites show which networks users actually click, and these insights continuously refine the global priority lists (for example, TikTok rising in Poland or WhatsApp trending among Spanish-language users). The JavaScript itself remains the same — it simply loads updated configs from the platform. This means network choice is context-aware, dynamic, and continuously improving, rather than static or hardcoded.