#iPhoneDuo Owners Report L-Shaped Screen Cracks Within 8-Hours of Purchase
It’s a two-grand contraption, dude! Where-T-F is #QualityControl, champ?! :confusedny:
#EarlyAdopters, ya know.
7 results for “KNTRO”
#iPhoneDuo Owners Report L-Shaped Screen Cracks Within 8-Hours of Purchase
It’s a two-grand contraption, dude! Where-T-F is #QualityControl, champ?! :confusedny:
#EarlyAdopters, ya know.
«[…] 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
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.
« #PublicacionesPúblicas» es el pariente hispano del #AllYourBaseAreBelongToUs. :skype_giggle:
Dos meses consecutivos sin actualizaciones mayores de Telegram. :tg:
Mepa que se viene a pique.
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:
LeadGenellikle 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:
0533 ..., +90 533 ..., 90533... gibi farklı biçimlerde saklanması.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:
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.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:
event_id aynı kalı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:
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:
occurred_at ile gönderim zamanı arasındaki fark. Satış ekibinin CRM'i geç güncellemesi burada hemen görünür.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ı
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).
🔔 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.
🔁 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.
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ć.
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ówDomyś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.
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ć?
🙇♂️ Zdecyduj samodzielnie, miej wyczucie.
Zdecydowanie ukrywaj:
Aplikacje
Android: Pachli
Czy macie jeszcze jakieś inne swoje rekomendacje?
~