• 05-03-2026, 14:55:50
    #1
    (ücreti mukabilinde)

    örnek çalışan site gösterebilirim özelden ama trendyol da güzel bir örnek.

    Trendyol da görmüşsünüzdür

    - son 24 saatte X kişi sepete Ekledi
    - Son 3 günde XX Kişi Favoriledi
    - Son 1 Günde X kişi satın aldı.

    bu 3 mesajı 2 sn aralıklarda değişecek şekilce manuel vermek istiyorum, site de ürün detay sayfasına ekleyeceğim. 3 mesaj içinde sabit değişkenler belirleyip x-y arasında sayı üret gibi olabilir.

    şu anda buna banzer bir yapıyı ben kullanıyorum ama o sadece XXX Kişi ziyaret etti mesajı veriyor sadece bunu 3 farklı mesaj verecek şekilde yapmak istiyorum.


    <script>
    (() => {
    "use strict";

    const CONFIG = {
    targetSelector: "#\30 > div > div > div.grid.grid-cols-1.sm\:grid-cols-1.md\:grid-cols-2.lg\:grid-cols-3.xl\:grid-cols-3 > div.product-detail-page-detail-box.relative.col-span-2.sm\:col-span-2.md\:col-span-2.px-4.lg\:col-span-1.xl\:col-span-1 > div.flex.flex-1.product-detail-page-buy-box.mt-4.mb-2.flex-col > div",
    widgetId: "bp-viewer-box",
    styleId: "bp-viewer-styles",
    startMin: 120,
    startMax: 480,
    clampMin: 45,
    clampMax: 980,
    stepDownMax: 7,
    stepUpMax: 11,
    intervalMin: 4000,
    intervalMax: 5200
    };

    /* RNG ve util */
    const hashStr = (s) => { let h = 2166136261>>>0; for (let i=0;i<s.length;i++){ h^=s.charCodeAt(i); h=Math.imul(h,16777619);} return h>>>0; };
    const makeRNG = (seed) => { let x=(seed||123456789)>>>0; return ()=>{ x^=x<<13; x>>>=0; x^=x>>17; x>>>=0; x^=x<<5; x>>>=0; return (x>>>0)/0xFFFFFFFF; }; };
    const between = (rng, min, max) => Math.floor(rng()*(max-min+1))+min;

    const productKey = (() => {
    const og=document.querySelector('meta[property="og:title"]');
    const title=og?.getAttribute("content")||document.title| |"";
    return location.origin+location.pathname+"|"+title.trim() ;
    })();
    const seed=hashStr(productKey);
    const rng=makeRNG(seed);
    const storeKey="bp_viewers_"+seed;
    const initialValue = (() => {
    const fromSession=sessionStorage.getItem(storeKey);
    if(fromSession) return parseInt(fromSession,10)||CONFIG.startMin;
    const v=between(rng,CONFIG.startMin,CONFIG.startMax);
    sessionStorage.setItem(storeKey,String(v));
    return v;
    })();
    let _value=initialValue;
    const setValue = => {
    _value=Math.max(CONFIG.clampMin,Math.min(CONFIG.cl ampMax,n));
    sessionStorage.setItem(storeKey,String(_value));
    const span=document.querySelector(`#${CONFIG.widgetId} .bp-viewer-count`);
    if(span) span.textContent=String(_value);
    };

    /* Stil */
    const ensureStyles = () => {
    if(document.getElementById(CONFIG.styleId)) return;
    const style=document.createElement("style");
    style.id=CONFIG.styleId;
    style.textContent=`
    #${CONFIG.widgetId} { width:100% !important; box-sizing:border-box; margin-top:16px; }
    .bp-viewer-box {
    display:flex; align-items:center; gap:8px;
    padding:10px 14px; background:#f8f8f8; border-radius:12px;
    font-family:system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
    font-size:16px; font-weight:600; width:100%;
    }
    .bp-viewer-icon { color:#ff5252; min-width:22px; }
    .bp-viewer-count { color:#ff5252; font-weight:700; margin:0 4px; }
    @media(max-width:480px){ .bp-viewer-box{ font-size:14px; padding:8px 12px; } }
    `;
    document.head.appendChild(style);
    };

    /* Widget oluştur */
    const buildWidget = (initial) => {
    const box=document.createElement("div");
    box.className="bp-viewer-box";
    box.id=CONFIG.widgetId;
    box.innerHTML=`
    <svg class="bp-viewer-icon" xmlns="http://www.w3.org/2000/svg" height="18" viewBox="0 0 24 24" width="18">
    <path fill="currentColor" d="M12 6c-5 0-9 3.6-10 6 1 2.4 5 6 10 6s9-3.6 10-6c-1-2.4-5-6-10-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4
    4-4 4 1.8 4 4-1.8 4-4 4z"></path>
    <circle fill="currentColor" cx="12" cy="12" r="2"></circle>
    </svg>
    <span><span class="bp-viewer-count">${initial}</span> kişi ürünü görüntülüyor!</span>
    `;
    return box;
    };

    const placeWidget = (target) => {
    let widget=document.getElementById(CONFIG.widgetId);
    if(!widget) widget=buildWidget(_value);
    if(target.nextElementSibling!==widget){
    target.insertAdjacentElement("afterend",widget);
    }
    };

    /* Güncelleme döngüsü */
    const scheduleNext = () => {
    const nextIn=between(rng,CONFIG.intervalMin,CONFIG.inter valMax);
    setTimeout(() => {
    const dirUp=rng()>0.44;
    const step=dirUp?between(rng,1,CONFIG.stepUpMax):-between(rng,1,CONFIG.stepDownMax);
    setValue(_value+step);
    scheduleNext();
    },nextIn);
    };

    /* Başlat */
    const start = () => {
    ensureStyles();
    const tryMount = () => {
    const target=document.querySelector(CONFIG.targetSelecto r);
    if(target){
    placeWidget(target);
    if(!window.__bpViewerStarted){
    window.__bpViewerStarted=true;
    scheduleNext();
    }
    observe(target);
    return true;
    }
    return false;
    };
    if(!tryMount()){
    const poll=setInterval(()=>{ if(tryMount()) clearInterval(poll); },300);
    const mo=new MutationObserver(()=>{ tryMount(); });
    mo.observe(document.documentElement||document.body ,{childList:true,subtree:true});
    }
    };

    const observe = (target) => {
    const mo=new MutationObserver(()=>{
    const t=document.querySelector(CONFIG.targetSelector);
    if(t) placeWidget(t);
    });
    mo.observe(document.documentElement||document.body ,{childList:true,subtree:true});
    };

    if(document.readyState==="complete"||document.read yState==="interactive") start();
    else {
    document.addEventListener("DOMContentLoaded",start ,{once:true});
    window.addEventListener("load",start,{once:true});
    }
    })();
    </script>
  • 05-03-2026, 15:02:09
    #2
    AI ile rahatlıkla çözebilirsiniz, boşuna ücret ödemeyin bence. AI'a istediğiniz şekilde direktif verebilir ve istediğiniz kadar revize yaptırırsınız. Cursor free trial başlangıç için oldukça yeterli olacaktır.
  • 05-03-2026, 15:03:11
    #3
    Technique adlı üyeden alıntı: mesajı görüntüle
    AI ile rahatlıkla çözebilirsiniz, boşuna ücret ödemeyin bence. AI'a istediğiniz şekilde direktif verebilir ve istediğiniz kadar revize yaptırırsınız. Cursor free trial başlangıç için oldukça yeterli olacaktır.
    anladığım işler değil hocam. Yapabilirseniz yardımcı olun lütfen ücretli ücretsiz farketmez
  • 05-03-2026, 15:10:01
    #4
    muyst adlı üyeden alıntı: mesajı görüntüle
    anladığım işler değil hocam. Yapabilirseniz yardımcı olun lütfen ücretli ücretsiz farketmez
    Spoiler olarak gönderdim, AI tam olarak hangi kaynak dosyasını düzenlemesi gerektiğini ve kodların içeriğini bilmediği için çok net bir çıktı üretebildi mi bilmiyorum ama belki işinize yarar. Dediğim gibi Cursor kullanmak çok basit hatta bunu direkt insanla konuşur gibi yapıyorsunuz bence bir denemenizde yarar var. Umarım kod işinize yarar.
    <script>
    (() => {
    "use strict";
    
    const CONFIG = {
    // Ürün detayda nereye eklenecek? (Sizdeki selector'u aynen koydum)
    targetSelector: "#30 > div > div > div.grid.grid-cols-1.sm:grid-cols-1.md:grid-cols-2.lg:grid-cols-3.xl:grid-cols-3 > div.product-detail-page-detail-box.relative.col-span-2.sm:col-span-2.md:col-span-2.px-4.lg:col-span-1.xl:col-span-1 > div.flex.flex-1.product-detail-page-buy-box.mt-4.mb-2.flex-col > div",
    
    widgetId: "bp-social-proof",
    styleId: "bp-social-proof-styles",
    
    // 2 saniyede bir mesaj değişsin
    rotateEveryMs: 2000,
    
    // Mesaj tanımları (MANUEL aralıkları buradan veriyorsunuz)
    messages: [
    {
    key: "cart",
    icon: "cart",
    template: (n) => `Son 24 saatte <span class="bp-count">${n}</span> kişi sepete ekledi`,
    min: 6,
    max: 42,
    // her dönüşte sayıyı küçük oynatmak isterseniz:
    stepDownMax: 2,
    stepUpMax: 3
    },
    {
    key: "fav",
    icon: "heart",
    template: (n) => `Son 3 günde <span class="bp-count">${n}</span> kişi favoriledi`,
    min: 15,
    max: 160,
    stepDownMax: 4,
    stepUpMax: 6
    },
    {
    key: "buy",
    icon: "bag",
    template: (n) => `Son 1 günde <span class="bp-count">${n}</span> kişi satın aldı`,
    min: 2,
    max: 28,
    stepDownMax: 1,
    stepUpMax: 2
    }
    ]
    };
    
    /* ---------- RNG + util (seed'li) ---------- */
    const hashStr = (s) => {
    let h = 2166136261 >>> 0;
    for (let i = 0; i < s.length; i++) {
    h ^= s.charCodeAt(i);
    h = Math.imul(h, 16777619);
    }
    return h >>> 0;
    };
    
    const makeRNG = (seed) => {
    let x = (seed || 123456789) >>> 0;
    return () => {
    x ^= x << 13; x >>>= 0;
    x ^= x >> 17; x >>>= 0;
    x ^= x << 5; x >>>= 0;
    return (x >>> 0) / 0xFFFFFFFF;
    };
    };
    
    const between = (rng, min, max) =>
    Math.floor(rng() * (max - min + 1)) + min;
    
    const clamp = (n, min, max) => Math.max(min, Math.min(max, n));
    
    /* ---------- Ürün bazlı seed ---------- */
    const productKey = (() => {
    const og = document.querySelector('meta[property="og:title"]');
    const title = (og?.getAttribute("content") || document.title || "").trim();
    return `${location.origin}${location.pathname}|${title}`;
    })();
    
    const seed = hashStr(productKey);
    const rng = makeRNG(seed);
    
    const storeKeyBase = `bp_sp_${seed}_`;
    
    const getStored = (k, fallback) => {
    const v = sessionStorage.getItem(storeKeyBase + k);
    const n = v ? parseInt(v, 10) : NaN;
    return Number.isFinite(n) ? n : fallback;
    };
    
    const setStored = (k, n) => {
    sessionStorage.setItem(storeKeyBase + k, String(n));
    };
    
    /* ---------- Stil ---------- */
    const ensureStyles = () => {
    if (document.getElementById(CONFIG.styleId)) return;
    
    const style = document.createElement("style");
    style.id = CONFIG.styleId;
    style.textContent = `
    #${CONFIG.widgetId}{
    width:100% !important;
    box-sizing:border-box;
    margin-top:14px;
    }
    #${CONFIG.widgetId} .bp-box{
    display:flex;
    align-items:center;
    gap:10px;
    padding:10px 14px;
    background:#f8f8f8;
    border-radius:12px;
    font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;
    font-size:15px;
    font-weight:600;
    width:100%;
    }
    #${CONFIG.widgetId} .bp-icon{
    width:20px;height:20px;min-width:20px;
    color:#ff5252;
    }
    #${CONFIG.widgetId} .bp-text{
    line-height:1.2;
    }
    #${CONFIG.widgetId} .bp-count{
    color:#ff5252;
    font-weight:800;
    }
    @media(max-width:480px){
    #${CONFIG.widgetId} .bp-box{font-size:14px;padding:8px 12px;}
    }
    `;
    document.head.appendChild(style);
    };
    
    /* ---------- Iconlar ---------- */
    const ICONS = {
    cart: `
    <svg class="bp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
    <path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2Zm10 0c-1.1 0-1.99.9-1.99 2S15.9 22 17 22s2-.9 2-2-.9-2-2-2ZM7.2 14h9.9c.75 0 1.41-.41 1.75-1.03L21 6H6.21L5.27 4H2v2h2l3.6 7.59-1.35 2.44C5.52 17.37 6.48 19 8 19h12v-2H8l1.2-3Z"/>
    </svg>`,
    heart: `
    <svg class="bp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
    <path d="M12 21s-7-4.35-9.33-8.28C.9 9.6 2.14 6.9 4.6 5.86 6.35 5.12 8.3 5.6 9.6 6.9L12 9.3l2.4-2.4c1.3-1.3 3.25-1.78 5-1.04 2.46 1.04 3.7 3.74 1.93 6.86C19 16.65 12 21 12 21z"/>
    </svg>`,
    bag: `
    <svg class="bp-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
    <path d="M6 7V6a6 6 0 0 1 12 0v1h3v15H3V7h3Zm2 0h8V6a4 4 0 0 0-8 0v1Zm-2 4h2v2H6v-2Zm10 0h2v2h-2v-2Z"/>
    </svg>`
    };
    
    /* ---------- Widget ---------- */
    const buildWidget = () => {
    const wrap = document.createElement("div");
    wrap.id = CONFIG.widgetId;
    wrap.innerHTML = `<div class="bp-box">
    <span class="bp-ico"></span>
    <span class="bp-text"></span>
    </div>`;
    return wrap;
    };
    
    const renderMessage = (msgIndex) => {
    const widget = document.getElementById(CONFIG.widgetId);
    if (!widget) return;
    
    const msg = CONFIG.messages[msgIndex];
    const iconEl = widget.querySelector(".bp-ico");
    const textEl = widget.querySelector(".bp-text");
    
    // sayı üret / dalgalandır
    const initial = between(rng, msg.min, msg.max);
    const current = getStored(msg.key, initial);
    
    // her gösterimde küçük step up/down (isterseniz)
    const dirUp = rng() > 0.45;
    const step = dirUp
    ? between(rng, 0, msg.stepUpMax ?? 0)
    : -between(rng, 0, msg.stepDownMax ?? 0);
    
    const nextVal = clamp(current + step, msg.min, msg.max);
    setStored(msg.key, nextVal);
    
    iconEl.innerHTML = ICONS[msg.icon] || ICONS.cart;
    textEl.innerHTML = msg.template(nextVal);
    };
    
    const placeWidget = (target) => {
    let widget = document.getElementById(CONFIG.widgetId);
    if (!widget) widget = buildWidget();
    if (target.nextElementSibling !== widget) {
    target.insertAdjacentElement("afterend", widget);
    }
    };
    
    /* ---------- Başlat / Döndür ---------- */
    let rotateTimer = null;
    let currentIndex = 0;
    
    const startRotate = () => {
    if (rotateTimer) return;
    
    renderMessage(currentIndex);
    rotateTimer = setInterval(() => {
    currentIndex = (currentIndex + 1) % CONFIG.messages.length;
    renderMessage(currentIndex);
    }, CONFIG.rotateEveryMs);
    };
    
    const mount = () => {
    ensureStyles();
    
    const tryMount = () => {
    const target = document.querySelector(CONFIG.targetSelector);
    if (!target) return false;
    
    placeWidget(target);
    startRotate();
    return true;
    };
    
    if (tryMount()) return;
    
    // hedef geç yüklenirse yakala
    const poll = setInterval(() => {
    if (tryMount()) clearInterval(poll);
    }, 300);
    
    const mo = new MutationObserver(() => tryMount());
    mo.observe(document.documentElement || document.body, { childList: true, subtree: true });
    };
    
    if (document.readyState === "complete" || document.readyState === "interactive") {
    mount();
    } else {
    document.addEventListener("DOMContentLoaded", mount, { once: true });
    window.addEventListener("load", mount, { once: true });
    }
    })();
    </script>