home.social

Search

7 results for “KNTRO”

  1. «[…] Desafortunadamente, en ese momento aún no era obligatorio que esta categoría de aeronave llevara una grabadora de voz de cabina.

    »Se estaba implementando una regla en octubre de ese mismo año que exigía instalar grabadoras de voz de cabina y —en un giro del destino realmente cruel— #SkyWest, de hecho, le había pedido a la #FAA que les permitiera instalar las grabadoras de voz antes de tiempo. Al hacerlo, también le habían pedido a la FAA una excepción a la obligación de dejar el avión en tierra si una #CVR no funcionaba —claro está— hasta la fecha de implementación oficial.

    »Pero, la FAA simplemente dijo que no a eso; si instalaban esos dispositivos antes de tiempo, también tendrían que funcionar para que la aeronave fuera aeronavegable. Y, obviamente, la #aerolínea no quería asumir ese riesgo adicional.

    »Desde mi punto de vista, esto es la #burocracia en su peor expresión».

    — #PetterHörnfeldt, #MentourPilot

    youtube.com/watch?v=Gjm4h4ni8js

    #USAir #FederalAviationAdministration

  2. Hablando de Meta, volví a ver este pleonasmo de pura casualidad y me dio mucha ternura. Qué genialidad.

    Ya tenía años en Facebook, pero parece que Meta usó la misma traducción en sus otros servicios.

    « » es el pariente hispano del . :skype_giggle:

  3. Dos meses consecutivos sin actualizaciones mayores de Telegram. :tg:

    Mepa que se viene a pique.

  4. Reklam panelinde "lead" sayısı artarken satış ekibinin "bu lead'lerin hiçbiri alıcı değil" demesi, dijital pazarlamada en sık duyduğum cümlelerden biri. Ben Koray Yalçın; lead yönetimi, CRM mimarisi, dijital pazarlama ve yapay zekâ destekli otomasyonların kesiştiği projelerde çalışıyorum, özellikle gayrimenkul ve B2B tarafında. Bu cümlenin arkasında çoğu zaman teknik bir kopukluk yatar: Reklam platformu formun doldurulduğunu bilir, ama o kişinin üç hafta sonra showroom'a gelip sözleşme imzaladığını bilmez. Algoritma da doğal olarak form doldurmaya en yatkın kitleyi bulmaya devam eder, satın almaya en yatkın kitleyi değil.

    Bu boşluğu kapatmanın yolu, CRM'de oluşan "nitelikli lead", "randevu gerçekleşti" ve "satış kapandı" gibi olayları sunucu tarafından Meta Conversions API'ye (CAPI) geri göndermek. Bu yazı bir pazarlama rehberi değil; bu köprüyü kodla kurarken karşılaştığım tasarım kararlarını anlatıyor: kullanıcı verisinin normalizasyonu ve hash'lenmesi, olay kimliği ile tekilleştirme, zaman penceresi, yeniden deneme stratejisi ve izin kontrolü. Örnekler Python ama mantık her dile taşınabilir.

    Önce olay sözlüğü: Hangi CRM durumu hangi olay?


    Kod yazmadan önce yapılması gereken en önemli iş, CRM'deki aşamaları sınırlı ve anlamlı bir olay listesine eşlemek. Her aşama değişikliğini Meta'ya göndermek gürültü üretir. Benim kullandığım tipik eşleme şöyle:

    CRM olayıGönderilen olay adıNotForm / lead oluştuLeadGenellikle tarayıcı pikseli zaten gönderirTemsilci "nitelikli" işaretlediQualifiedLead (özel olay)Ölçüm kurgusuna göre seçilirRandevu gerçekleştiSchedule veya özel olay"Randevu alındı" değil, "gerçekleşti"Sözleşme imzalandıPurchasevalue ve currency zorunlu düşünülmeli


    Burada kritik nokta şu: Olay, CRM'de geri alınabilir bir alan değişikliğinden değil, kalıcı bir olaydan tetiklenmeli. Temsilci bir fırsatı yanlışlıkla "kazanıldı" yapıp beş dakika sonra geri alırsa, gönderilmiş bir Purchase olayını geri çekmenin pratik bir yolu yoktur. Bu yüzden ben aşama değişikliklerini doğrudan API'ye bağlamak yerine bir conversion_events tablosuna yazıyorum ve gönderimi kısa bir bekleme süresinden sonra yapan ayrı bir işçiye bırakıyorum.

    CREATE TABLE conversion_events (
    id BIGSERIAL PRIMARY KEY,
    event_id TEXT NOT NULL UNIQUE, -- tekilleştirme anahtarı
    event_name TEXT NOT NULL,
    lead_id BIGINT NOT NULL REFERENCES leads(id),
    occurred_at TIMESTAMPTZ NOT NULL, -- olayın gerçek zamanı
    value_minor BIGINT, -- kuruş/cent cinsinden
    currency CHAR(3),
    status TEXT NOT NULL DEFAULT 'pending', -- pending, sent, failed, skipped
    attempts INT NOT NULL DEFAULT 0,
    last_error TEXT,
    send_after TIMESTAMPTZ NOT NULL DEFAULT now() + interval '15 minutes'
    );

    send_after alanı, "yanlışlıkla kazanıldı" senaryosuna karşı küçük bir tampon. İşçi göndermeden önce fırsatın hâlâ aynı aşamada olup olmadığını kontrol eder; değilse kaydı skipped yapar.

    Kullanıcı verisini normalize etmek: Hash'ten önce gelen asıl iş


    CAPI, e-posta ve telefon gibi kişisel verilerin SHA-256 ile hash'lenmiş olarak gönderilmesini bekler. Çoğu ekip hashlib.sha256(email) yazıp işi bitmiş sayar. Sorun şu ki hash, girdideki tek bir boşluğu ya da büyük harfi tamamen farklı bir değere dönüştürür. Meta tarafındaki eşleşme de birebir karşılaştırmayla çalıştığı için normalizasyon hatası, sessizce düşük eşleşme oranı olarak geri döner.

    Benim sahada gördüğüm en yaygın hatalar:

    • E-postada baştaki/sondaki boşluklar ve büyük harfler.
    • Telefonun 0533 ..., +90 533 ..., 90533... gibi farklı biçimlerde saklanması.
    • İsimlerde Türkçe karakterlerin farklı yazımları ve "Dr." gibi önekler.
    • Boş alanların boş string olarak hash'lenmesi (boş string'in de bir SHA-256 değeri vardır ve anlamsız bir eşleşme anahtarı üretir).

    import hashlib
    import re
    import phonenumbers

    def _sha256(value: str) -> str:
    return hashlib.sha256(value.encode("utf-8")).hexdigest()

    def norm_email(raw: str | None) -> str | None:
    if not raw:
    return None
    v = raw.strip().lower()
    return v if "@" in v else None

    def norm_phone(raw: str | None, default_region: str = "TR") -> str | None:
    if not raw:
    return None
    try:
    num = phonenumbers.parse(raw, default_region)
    except phonenumbers.NumberParseException:
    return None
    if not phonenumbers.is_valid_number(num):
    return None
    # Ülke kodu dahil, yalnızca rakamlar, başta + yok
    return phonenumbers.format_number(num, phonenumbers.PhoneNumberFormat.E164).lstrip("+")

    def build_user_data(lead) -> dict:
    ud = {}
    if (e := norm_email(lead.email)):
    ud["em"] = [_sha256(e)]
    if (p := norm_phone(lead.phone, lead.country_code or "TR")):
    ud["ph"] = [_sha256(p)]
    if lead.external_id:
    ud["external_id"] = [_sha256(str(lead.external_id))]
    # Tarayıcıdan yakalandıysa hash'lenmeden gönderilen alanlar
    if lead.fbc:
    ud["fbc"] = lead.fbc
    if lead.fbp:
    ud["fbp"] = lead.fbp
    return ud

    Bir detay daha: Kıbrıs gibi çok uluslu alıcı kitlesi olan pazarlarda default_region sabit "TR" olamaz. İngiltere'den gelen bir lead'in 07... ile başlayan numarası Türkiye varsayımıyla ayrıştırılırsa geçersiz sayılır ya da daha kötüsü yanlış bir numara üretir. Bu yüzden formda ülke seçimini ayrı bir alan olarak tutmak, normalizasyonun doğruluğunu doğrudan etkiliyor.

    fbc, fbp ve external_id: Eşleşmeyi güçlendiren köprüler


    E-posta ve telefon tek başına çoğu zaman yeterli olur, ama iki alan eşleşme kalitesini belirgin biçimde artırır:

    • fbc: Reklam tıklamasıyla gelen fbclid parametresinden türetilen tıklama kimliği. Kullanıcı sitenize reklamla geldiyse _fbc çerezinde bulunur.
    • fbp: Pikselin tarayıcıya yazdığı _fbp çerezi.

    Bu değerler satış anında değil, lead oluştuğu anda yakalanmalı. Üç hafta sonra sözleşme imzalanırken kullanıcı tarayıcısında değil, satış ofisinde oturuyor. Bu nedenle form gönderiminde bu iki çerezi gizli alanlarla alıp lead kaydına yazmak, sonraki tüm offline olayların kalitesini belirliyor. Meta Lead Ads formlarından gelen lead'lerde ise platformun verdiği lead kimliğini saklamak aynı işi görür; CRM entegrasyonu senaryolarında bu kimliğin olayla birlikte gönderilmesi eşleşmeyi doğrudan kurar.

    external_id ise sizin CRM'deki kişi kimliğiniz. Hem piksel hem sunucu tarafında aynı değer (hash'lenmiş olarak) gönderilirse, aynı kişinin farklı olaylarını birbirine bağlamak kolaylaşır.

    event_id ile tekilleştirme: Aynı satışı iki kez saymamak


    CAPI'de iki ayrı tekrar riski vardır:

    1. Piksel ile sunucu çakışması: Lead olayını hem tarayıcı pikseli hem sunucu gönderiyorsa, iki olay aynı event_name ve aynı event_id ile gelmelidir. Meta bu ikiliyi tek olay olarak sayar.
    2. Yeniden deneme çakışması: Ağ zaman aşımı yüzünden isteğin ulaşıp ulaşmadığını bilmiyorsanız ve tekrar gönderirseniz, aynı event_id korunmalıdır.

    event_id rastgele üretilmemeli; olaydan deterministik olarak türetilmeli. Benim tercihim şu:

    def make_event_id(event_name: str, lead_id: int, stage_version: int) -> str:
    return f"{event_name.lower()}:{lead_id}:{stage_version}"

    stage_version, fırsatın o aşamaya kaçıncı kez girdiğini tutan bir sayaç. Böylece bir müşteri gerçekten ikinci bir daire satın alırsa yeni bir Purchase üretilir, ama aynı satış için yapılan iki gönderim aynı kimliği taşır. Veritabanındaki UNIQUE kısıtı da aynı olayın kuyruğa iki kez girmesini engeller.

    Zaman penceresi: event_time "şimdi" değil, olayın gerçek zamanıdır


    Offline satış entegrasyonunda en sık yapılan hata, event_time alanına gönderim anını yazmak. Olayın değeri, ne zaman gerçekleştiğiyle anlam kazanır; sözleşme salı günü imzalandıysa ve işçi çarşamba gönderdiyse, event_time salı olmalıdır.

    İkinci önemli nokta, Meta'nın kabul ettiği geriye dönük pencere. Bu yazıyı yazarken belgeler, olayların gerçekleştikten sonra sınırlı bir süre içinde gönderilmesini istiyor ve bu süre action_source değerine göre farklılaşabiliyor. Sınır zamanla değişebildiği için kodda sabit bir sayı gömmek yerine yapılandırmadan okuyorum ve pencereyi aşmış olayları göndermeyi denemek yerine skipped olarak işaretleyip raporluyorum:

    from datetime import datetime, timezone, timedelta

    MAX_AGE = { # yapılandırmadan gelir; güncel değeri resmi belgeden doğrulayın
    "system_generated": timedelta(days=7),
    "physical_store": timedelta(days=7),
    }

    def is_sendable(evt, action_source: str) -> bool:
    age = datetime.now(timezone.utc) - evt.occurred_at
    return age <= MAX_AGE.get(action_source, timedelta(days=7))

    Bu kontrolün pratik sonucu, satış ekibinin CRM'i zamanında güncellemesinin bir veri kalitesi konusu haline gelmesi. Sözleşmeyi on gün sonra sisteme giren bir ekip, reklam optimizasyonuna o satışı hiç kazandıramaz. Bu yüzden ben bu entegrasyonu kurarken satış ekibi için "sözleşme imzalandığı gün CRM'de kapanır" kuralını da süreç tarafında yazılı hale getiriyorum.

    action_source ve olay gövdesi


    Sunucudan giden olay gövdesinin iskeleti şöyle:

    def build_payload(evt, lead, action_source="system_generated") -> dict:
    data = {
    "event_name": evt.event_name,
    "event_time": int(evt.occurred_at.timestamp()),
    "event_id": evt.event_id,
    "action_source": action_source,
    "user_data": build_user_data(lead),
    }
    if evt.value_minor is not None:
    data["custom_data"] = {
    "value": evt.value_minor / 100,
    "currency": evt.currency,
    }
    return {"data": [data]}

    action_source alanı, olayın nerede gerçekleştiğini anlatır. Web formu için website, CRM'in kendi ürettiği aşama değişiklikleri için system_generated, satış ofisinde imzalanan sözleşme için physical_store gibi değerler kullanılabilir. Doğru değeri seçmek hem raporlamayı hem de uygulanan kuralları etkiler; bu yüzden olay sözlüğünde her olayın action_source değerini de sabitliyorum.

    value tarafında bir uyarı: Konut gibi yüksek tutarlı satışlarda gerçek sözleşme bedelini göndermek bazı ekiplerin istemediği bir şey olabilir. Bu durumda tutarlı bir "değer skalası" (örneğin ürün tipine göre sabit bir puan) kullanmak, optimizasyon sinyalini korurken hassas ticari bilgiyi dışarı çıkarmamanın bir yolu. Hangisi seçilirse seçilsin, tutarlılık önemlidir; ay ortasında yöntemi değiştirmek raporları kırar.

    Gönderim işçisi: Toplu istek, yeniden deneme ve hata sınıflandırma


    İşçinin görevi basit görünür ama hata sınıflandırması önemli:

    import requests, time

    def send_batch(events, leads, pixel_id, token):
    payload = {"data": []}
    for evt in events:
    payload["data"].extend(build_payload(evt, leads[evt.lead_id])["data"])
    url = f"https://graph.facebook.com/{API_VERSION}/{pixel_id}/events"
    resp = requests.post(url, params={"access_token": token}, json=payload, timeout=15)
    if resp.status_code >= 500 or resp.status_code == 429:
    raise RetryableError(resp.text) # üstel bekleme ile tekrar
    if resp.status_code >= 400:
    raise PermanentError(resp.text) # kaydı failed yap, alarm üret
    return resp.json()

    Kurallarım:

    • 5xx ve hız sınırı hataları yeniden denenir; bekleme süresi her denemede artar ve event_id aynı kalır.
    • 4xx hatalar (geçersiz parametre, süresi dolmuş token) yeniden denenmez. Tekrar göndermek sonucu değiştirmez, yalnızca log kirletir. Bunlar bir alarm kanalına düşer.
    • Token kod içinde değil, gizli değişken yönetiminde tutulur ve süresi izlenir. Sistem kullanıcısı token'ı kullanmak, bir çalışanın hesabı kapandığında entegrasyonun sessizce durmasını engeller.
    • Test olay kodu ile canlıya geçmeden önce olayların Events Manager'daki test ekranında doğru göründüğü doğrulanır.


    İzin ve veri minimizasyonu


    Kişisel veriyi üçüncü bir platforma, hash'lenmiş olsa bile, göndermek bir hukuki dayanak gerektirir. Türkiye'de KVKK, Avrupa'dan gelen alıcılar için GDPR bu çerçeveyi çizer. Benim teknik tarafta uyguladığım kurallar:

    • Lead kaydında reklam ölçümüne ilişkin izin durumu ayrı bir alan olarak tutulur ve işçi, izni olmayan kişi için olay göndermez.
    • Yalnızca eşleşme için gerekli alanlar gönderilir; adres, doğum tarihi gibi alanlar "olsa iyi olur" diye eklenmez.
    • İzin geri çekildiğinde, kuyruktaki bekleyen olaylar da iptal edilir.

    Bu bir hukuki görüş değil; ama izin kontrolünü kodun içine bir if olarak gömmek, sonradan "kimin verisi nereye gitti" sorusuna cevap verebilmeyi sağlıyor.

    Ölçüm: Entegrasyon gerçekten çalışıyor mu?


    Kurulumdan sonra baktığım üç gösterge var:

    1. Eşleşme kalitesi: Events Manager'daki olay eşleşme göstergesi. Düşükse ilk şüpheli normalizasyondur.
    2. Gecikme dağılımı: occurred_at ile gönderim zamanı arasındaki fark. Satış ekibinin CRM'i geç güncellemesi burada hemen görünür.
    3. CRM ile panel karşılaştırması: Aylık kapanan satış sayısı ile Meta'nın aldığı Purchase sayısı arasındaki fark. Birebir tutması beklenmez, ama fark aniden açılırsa token, izin veya şema tarafında bir şey bozulmuştur.


    Sıkça Sorulan Sorular


    Piksel zaten kurulu, neden ayrıca CAPI gerekiyor?
    Piksel yalnızca tarayıcıda olan olayları görür. Telefonla kapanan, satış ofisinde imzalanan ya da haftalar sonra gerçekleşen satışlar tarayıcıda olmaz. CAPI, bu olayları CRM'den doğrudan göndermeyi sağlar.

    E-postayı hash'lemeden göndersem Meta kendisi hash'lemez mi?
    Bazı resmi kütüphaneler hash işlemini kendisi yapar, ama kendi kodunuzla gönderiyorsanız normalizasyon ve hash sizin sorumluluğunuzdadır. Kontrolü elde tutmak, hatayı ayıklamayı da kolaylaştırır.

    Aynı satışı yanlışlıkla iki kez gönderirsem ne olur?
    Aynı event_name ve event_id ile gönderildiyse tekilleştirilir. Farklı kimlikle gönderildiyse iki satış sayılır; bu yüzden kimliği deterministik üretmek önemlidir.

    Satış on gün sonra CRM'e girildi, yine de gönderebilir miyim?
    Meta'nın kabul ettiği geriye dönük pencereyi aşmışsa olay reddedilir. Güncel sınırı resmi belgeden kontrol edin ve asıl çözümü süreçte arayın: satış, gerçekleştiği gün CRM'e girilmeli.

    Gerçek sözleşme bedelini göndermek zorunda mıyım?
    Hayır. Tutarlı bir değer skalası da optimizasyon için yeterli sinyal üretebilir. Önemli olan, seçilen yöntemin zaman içinde değişmemesi.

    Bu entegrasyon küçük ekipler için fazla karmaşık değil mi?
    Kuyruk tablosu, normalizasyon fonksiyonu ve bir gönderim işçisi birkaç yüz satır kod demek. Karşılığında reklam algoritması form dolduranları değil, satın alanları öğrenmeye başlar. Lead hacmi düşük ama satış değeri yüksek sektörlerde bu fark özellikle belirgin.

    Koray Yalçın — lead yönetimi, CRM mimarisi, dijital pazarlama ve gayrimenkul teknolojileri (PropTech) üzerine çalışıyorum. CRM'den reklam platformlarına geri bildirim kurarken sizi en çok hangi adım zorladı? Yorumlarda konuşalım.#backend #crm #api #marketing #software #coding #development #engineering #inclusive #community
    CRM'de kapanan satışı Meta Conversions API'ye geri bildirmek: Hash, event_id ve zaman penceresi üzerine geliştirici notları

  5. Widząc, jak przybywa nowych użytkowników na Mastodonie, przygotowałem kilka wskazówek, które mogą pomóc w korzystaniu z platformy.

    Nawigacja: główne zakładki

    🏠 Strona główna
    Posty (tooty) osób, które obserwujesz, oraz ich podbicia (udostępnienia).

    • Toot - nazwa postu (wiadomości) w sieci Mastodon.

    🔔 Powiadienia
    Wzmianki, polubienia, podbicia, nowi obserwacjy, interakcje na własne treści.

    👥 Lokalne
    Publiczne toot‑y z instancji, w której jesteś zarejestrowany. Odkrywanie treści i użytkowników z własnego serwera.

    🔍 Odkrywaj
    Tematy, konta, hashtagi - wprowadź słowo, a następnie wyszukaj, (np. „cyfrowego").

    🕸️ Globalne (Federacja)
    Publiczne toot‑y z całej sieci Mastodon (wszystkich instancji). Pozwala zobaczyć, co dzieje się w szerszej społeczności.

    Kluczowe akcje: Jak reagować na posty?

    🔁 Podbicie
    Podbijaj, Podawaj dalej (Boostuj): To główny silnik napędowy Mastodona. Dzięki temu wspierasz innych twórców i zyskujesz nowych obserwujących. To główny sposób na budowanie społeczności. Jeśli podobna Ci się się podoba post, podbije go.

    ⭐ Polubienie
    Wyrażasz uznanie dla postu. Powiadomienie zostanie przesłane wyłącznie Tobie oraz autorowi. Post nie rozchodzi się dalej jak w przypadku podbicia.

    🤔 Nie bój się pytać!
    Mastodon to społeczność, która chętnie pomaga. Jeśli coś jest niejasne, zapytaj publicznie na pewno ktoś Ci pomoże! 🐘
    I tutaj możemy przejść do hashtagów:

    💡 Warto wiedzieć, warto używać

    # Hashtag
    Przykłady: (#)zapytajfedi (#)fedisiępyta (#)fedipomoc Dzięki hashtagom zwiększysz zasięgi, tylko nie przesadzaj z ich ilością! Więcej o tym, jak korzystać z hashtagów, dowiesz się w dalszej części.

    🌿 Spokojna głowa

    Dbaj o stan swojego umysłu, naturalnie nie musisz się ze wszystkimi zgadzać. Z pomocą przychodzą następujące funkcje:

    🔇 Wyciszenie
    Ukrywasz posty konkretnego użytkownika, nie blokując go. On nie wie, że go wyciszyłeś. Świetny sposób na osoby, które Cię irytują.

    🚫 Blokada
    Przerywasz kontakt. Osoba nie widzi Twoich postów i nie może Cię obserwować.

    Zarządzanie treściami

    Każdy post można oznaczyć poziomem dostępu:

    🌍 Publiczny
    Wszyscy go widzą (również osoby bez konta).

    🔒 Dla obserwujących
    Widzą go tylko osoby, które Cię obserwują.

    🔐 Bezpośredni
    Widzi tylko osoba, do której piszesz.

    Zawsze możesz edytować lub usunąć swój post. Mastodon daje Ci kontrolę nad swoją treścią.

    Ustawienie języka dla postów

    Domyślny język
    Jeśli Twój profil jest ustawiony na język polski, Mastodon automatycznie oznacza każdy nowy post jako polski. W większości przypadków ręczne ustawienie nie jest więc konieczne.

    Kontrola w przypadku wielojęzyczności
    Jeśli piszesz posty w różnych językach (np. mieszanina PL/EN), ręczne ustawienie języka może zwiększyć widoczność.

    ⚠️ Ustawienie języka na Mastodon jest ważne, ponieważ:

    • Poprawia działanie tłumaczeń Wbudowany system tłumaczeń wykorzystuje oznaczenie języka wpisu, błędne oznaczenie może skutkować brakiem tłumaczenia.

    • Zwiększenie widoczności
      Właściwe oznaczenie wpisu zapobiega jego przypadkowemu ukryciu przez filtry i pozwala dotrzeć do szerszego grona odbiorców.

    • Szacunek do społeczności
      Poprawne oznaczenie języka, to prosty sposób, by okazać szacunek innym użytkownikom.

    Ukrywanie treści

    Oznaczenie postu jako „wrażliwy"
    Ukrywa zawartość za przyciskiem „Pokaż zawartość wrażliwą", co pozwala użytkownikom świadomie zdecydować, czy ją obejrzeć.

    Kiedy używać?

    • Sensacyjne treści (wypadki, drastyczne sceny)
    • Treści, które mogą być traumatyczne lub obraźliwe
    • Użytkownicy często ukrywają treści, polaryzacyjne np. polityczne.

    🙇‍♂️ Zdecyduj samodzielnie, miej wyczucie.

    Zdecydowanie ukrywaj:

    • Przemoc, krew, okrucieństwo
    • Nagość lub seksualność (do takiej tematyki istnieją osobne, dedykowane serwery).
    ✨ Rekomendacje

    Aplikacje

    Android: Pachli

    Czy macie jeszcze jakieś inne swoje rekomendacje?

    ~

Share on Mastodon

Enter the server where you have an account.