4 คะแนน โดย GN⁺ 2023-11-03 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Bear Blog สร้าง ระบบวิเคราะห์ของตัวเอง ที่ทำงานได้โดยไม่ใช้ JavaScript ฝั่งไคลเอนต์ เนื่องจากข้อจำกัดด้านความเร็ว ประสิทธิภาพ และความเสถียร
  • สคริปต์วิเคราะห์ทั่วไปอาจถูก ad blocker บล็อกได้ และถ้าใช้แค่ server logs ก็อาจมีทั้ง crawler, scraper และ parser ที่ใช้ GPT ปะปนเข้ามา ทำให้ สถิติผู้เข้าชมบิดเบือน
  • เมื่อเกิด body:hover ใน CSS ของแต่ละหน้า จะเรียก endpoint /hit/{{ post.id }}/ ผ่าน border-image และใช้ hover หรือการเลื่อนหน้าบนมือถือเป็น สัญญาณการอ่าน
  • เซิร์ฟเวอร์ตรวจสอบจาก user-agent ว่าเป็นบ็อตหรือไม่ รวมถึงดูเบราว์เซอร์และแพลตฟอร์ม ส่วน IP address ใช้เฉพาะเพื่อระบุประเทศ จากนั้นลบการอ่านซ้ำด้วย แฮช IP+วันที่
  • หากอ่านจากหลายอุปกรณ์ในวันเดียวกันภายใต้ IP เดียวกัน จะนับเป็นครั้งเดียว แต่ยังสามารถรวมยอด จำนวนการอ่านไม่ซ้ำ แยกตามหน้าได้อย่างเรียบง่ายโดยไม่เก็บข้อมูลระบุตัวตน

สร้างอีเวนต์การอ่านด้วย CSS hover

  • ระบบวิเคราะห์ของ Bear Blog ทำตามข้อจำกัดที่ว่าไม่ใช้ JavaScript ฝั่งไคลเอนต์
  • เครื่องมือวิเคราะห์ทั่วไปใช้ JavaScript ฝั่งไคลเอนต์เพื่อช่วยตัดสินบางส่วนว่าทราฟฟิกเป็นของจริงหรือเป็นบ็อต แต่ ad blocker จำนวนมากไม่ได้บล็อกแค่ Google Analytics เท่านั้น ยังบล็อกสคริปต์วิเคราะห์อย่าง Fathom และ Plausible ด้วย
  • การ parse server logs เพียงอย่างเดียวอาจทำให้ crawler ของ search engine, scraper และ parser ที่ใช้ GPT ปะปนเหมือนเป็นทราฟฟิกปกติ จนเกิด มุมมองที่บิดเบือน
  • Bear ใส่ CSS ต่อไปนี้ในแต่ละหน้า เพื่อให้เกิด body:hover เมื่อผู้ใช้วางเคอร์เซอร์บนหน้า หรือเลื่อนหน้าบนมือถือ
body:hover {
  border-image: url("/hit/{{ post.id }}/?ref={{ request.META.HTTP_REFERER }}");
}
  • เมื่อ body:hover ถูก trigger ก็จะมีการเรียก hit URL ของบทความนั้น
  • ข้อมูลที่เพิ่มกลับเข้าไปอย่างชัดเจนใน request นี้คือ referrer และการสะกด HTTP_REFERER เป็น รูปแบบที่สะกดผิดแต่ตกค้างมาเหมือนเป็นมาตรฐาน
  • อาศัยข้อเท็จจริงที่ว่าบ็อตไม่ hover จึงใช้การเรียกแบบอิง body:hover เป็นสัญญาณของ ผู้อ่านที่เป็นมนุษย์
  • หลังจากนั้นเซิร์ฟเวอร์จะตรวจสอบว่า user-agent เป็นบ็อตหรือไม่ และดึงข้อมูลเบราว์เซอร์กับแพลตฟอร์มจากสตริง user-agent

ลบการอ่านซ้ำโดยไม่ใช้ข้อมูลระบุตัวตน

  • ข้อจำกัดข้อที่สองคือไม่เก็บข้อมูลที่สามารถระบุตัวผู้อ่านได้ไว้ใน browser cookie หรือบนเซิร์ฟเวอร์
  • IP address ใช้เฉพาะเพื่อระบุประเทศ และก่อนบันทึกจะ แฮช IP address ร่วมกับวันที่
  • request ต่อ ๆ มาสำหรับหน้าเดียวกันจะถูกนำไปเทียบกับแฮช IP address + วันที่ และทิ้งหากเป็นรายการซ้ำ
  • ด้วยวิธีนี้ หนึ่ง IP address จะถูกนับเป็นหนึ่ง read ต่อหนึ่งหน้าในช่วงหนึ่งวัน
  • จะไม่บันทึก IP address ต้นฉบับ และแฮชที่รวมวันที่ไว้จะมีผลเหมือนหมดอายุเป็นรายวัน
user_agent = httpagentparser.detect(self.request.META.get('HTTP_USER_AGENT', None))
if user_agent.get('bot', False):
    print('Bot traffic')
    return

ip_hash = hashlib.md5(f"{client_ip(self.request)}-{timezone.now().date()}".encode('utf-8')).hexdigest()
country = get_user_location(client_ip(self.request)).get('country_name', '')
device = user_agent.get('platform', {}).get('name', '')
browser = user_agent.get('browser', {}).get('name', '')
referrer = self.request.GET.get('ref', '')

if referrer:
    referrer = urlparse(referrer)
    referrer = '{uri.scheme}://{uri.netloc}/'.format(uri=referrer)

Hit.objects.get_or_create(
    post_id=self.pk,
    ip_address=ip_hash,
    referrer=referrer,
    country=country,
    device=device,
    browser=browser)
  • IP hash ใช้เพียงเพื่อกัน hit ซ้ำภายในหนึ่งวัน และโดยพื้นฐานแล้วการดูหน้าทุกครั้งจะถูกจัดการแบบไม่ซ้ำกัน
  • เมื่อสิ้นสุดแต่ละวัน งานเบื้องหลังจะลบแฮชออกจาก hit logs เพื่อไม่ให้ขัดกับการตีความ GDPR ที่เข้มงวดเกินไป
  • ข้อเสียของวิธีนี้คือ หากอ่านจากหลายอุปกรณ์ในวันเดียวกันภายใต้ IP address เดียวกัน ก็จะถูกนับเป็น read เดียวเท่านั้น
  • Bear มองว่ากรณีเช่นนี้เป็นเพียงส่วนน้อยของทราฟฟิก และเห็นว่าวิธีที่ใช้ CSS นี้ให้จำนวนการอ่านที่กระชับ เรียบง่าย และแม่นยำกว่าวิธีเก็บข้อมูลวิเคราะห์แบบอื่น ๆ หลายวิธี

1 ความคิดเห็น

 
GN⁺ 2023-11-03
ความคิดเห็นจาก Hacker News
  • ผมเป็นผู้เขียนเอง แฮชของที่อยู่ IP ในบริบทนี้ใช้เพียงเพื่อป้องกันการนับการเข้าชมซ้ำภายในวันเดียวเท่านั้น
    มีไว้เพื่อทำให้การเข้าชมหน้าแต่ละครั้งโดยพื้นฐานแล้วไม่ซ้ำกัน และเมื่อจบแต่ละวัน งาน worker จะล้างแฮชออกโดยยังคงข้อมูลการเข้าชมไว้ ผมได้เพิ่มการแก้ไขในบทความเพื่อชี้แจงเรื่องนี้แล้ว

    • สงสัยว่าเคยพิจารณาวิธีเสิร์ฟ ภาพโปร่งใสขนาดเล็ก จริง ๆ พร้อมเฮดเดอร์แคชแบบส่วนตัวที่หมดอายุตอนเที่ยงคืน และไม่เก็บ IP เลยหรือเปล่า
    • ถ้าผู้ใช้ 10 คนบน VPN ร่วมจากทั่วโลกใช้ IP เดียวกันแล้วเข้ามาในไซต์ จะนับเป็นแค่ 1 คนใช่ไหม? กรณีเครือข่ายบริษัทก็เช่นกัน และ IP เป็นตัวชี้วัดที่แย่
  • ตอนเห็นไอเดียการใช้ request ที่เกิดจาก CSS มาทำ analytics ครั้งแรก รู้สึกว่ามันเจ๋งมาก
    มีคนหนึ่งใน Twitter วางตารางสี่เหลี่ยมที่มองไม่เห็นไว้บนหน้า แล้วให้แต่ละช่องโหลดภาพพื้นหลังเฉพาะของตัวเองเมื่อ hover เพื่อใช้ทำ การติดตามเมาส์ ภาพพื้นหลังแต่ละภาพจะส่ง request เฉพาะไปยังเซิร์ฟเวอร์ แล้วเซิร์ฟเวอร์ตีความ request นั้น
    ฤดูร้อนปีหนึ่ง ผมขยายไอเดียนี้เล่น ๆ จนทำ “เว็บแชตแบบอะซิงโครนัสที่ใช้เฉพาะ CSS” โดยไม่มี JavaScript: https://github.com/kkuchta/css-only-chat

  • การบอกว่าทำให้ที่อยู่ IP เป็นนิรนามด้วยการแฮชแค่วันที่กับ IP นั้นเป็นแค่ ละครความปลอดภัย
    แฮชเชิงเข้ารหัสถูกออกแบบมาให้คำนวณได้เร็ว ใช้ hashcat บน MacBook M1 Pro คำนวณแฮช MD5 ได้ 6 พันล้านรายการต่อวินาที และที่อยู่ IPv4 มีแค่ 4 พันล้านรายการเท่านั้น สามารถ brute force ทั้งช่วงเพื่อหาที่อยู่ IP ได้ จึงแทบไม่ต่างจากการย้อนแฮช
    ต่อให้ใช้แฮชที่ปลอดภัยอย่าง SHA-256 แทน MD5 ที่พังแล้ว ก็ยังเหมือนเดิม

    • นอกเหนือจากข้อเท็จจริงที่ว่าการกู้ IP กลับจากแฮชนั้นเป็นเรื่องเล็กน้อยในเชิงเทคนิค หน่วยงานคุ้มครองข้อมูลของ EU ก็ระบุไว้อย่างชัดเจนมากว่า การแฮชข้อมูลส่วนบุคคลไม่ได้ทำให้เป็นนิรนาม
      ต่อให้แฮชชื่อนามสกุลของใครสักคน ภายหลังก็ยังตอบคำถามได้ว่า “แฮชนี้ตรงกับชื่อนามสกุลเฉพาะนี้หรือไม่” การตอบคำถามนี้ได้หมายความว่ากระบวนการทำให้เป็นนิรนามนั้นย้อนกลับได้
    • ผมเป็นผู้เขียนเอง ผมคอมเมนต์ไว้ข้างล่างแล้ว แต่ดูเหมือนจะเกี่ยวกับเธรดนี้มากกว่า
      แฮชของที่อยู่ IP ในบริบทนี้ใช้เพียงเพื่อป้องกันการนับการเข้าชมซ้ำภายในวันเดียวเท่านั้น มีไว้เพื่อทำให้การเข้าชมหน้าแต่ละครั้งโดยพื้นฐานแล้วไม่ซ้ำกัน และเมื่อจบแต่ละวัน งาน worker จะลบแฮช IP ที่ไม่จำเป็นอีกต่อไปออก
    • อ้างอิงเพิ่มเติม ประเด็นเดียวกันนี้เคยถูกยกขึ้นในการสนทนาเรื่องที่ Storybook ทำสิ่งคล้ายกันกับ telemetry[0] และแม้ไม่ทำ optimization ใด ๆ เลย แล็ปท็อปบ้านของผมก็ใช้เวลาประมาณสองชั่วโมงในการคำนวณ แฮชที่ใส่ salt สำหรับ IPv4 ทั้งหมด
      [0] https://news.ycombinator.com/item?id=37596757
    • แฮชควรต้องใส่ salt ถ้าใช้ salt ก็โอเค ถ้าไม่ใช้ก็ไม่โอเค
      จะเก็บ salt ถาวรหรือหมุนเปลี่ยนเป็นระยะ ๆ นั้นเป็นเพียงรายละเอียดการ implement และประเด็นสำคัญเมื่อใส่ salt ให้แฮชเพื่อ analytics คือ salt ต้องไม่ออกจากฝั่งไคลเอนต์เด็ดขาด
      จากคำอธิบายในบทความดูเหมือนจะไม่มี salt หรืออาจใช้วันที่ปัจจุบันเป็นเหมือน salt ซึ่งไม่ใช่ salt แบบสุ่ม ดังนั้นใครก็ตามที่อยากรู้ว่า “IP x.y.z.w เข้ามาในวันที่ yy-mm-dd หรือไม่?” ก็เดาได้ง่าย
      ถ้ามองจากมุมของผู้โจมตี จะตัดสินปัญหาแบบนี้ได้ง่าย ถ้ามีข้อมูลชุดนี้แล้วจะหาข้อมูลอะไรเกี่ยวกับบุคคลหนึ่งได้อย่างไร? ถ้าทำไม่ได้ ข้อมูลนั้นโดยทั่วไปก็มีแนวโน้มจะเก็บได้อย่างปลอดภัย
    • ใช้ secret salt หรือ rotating salt ก็ได้นี่? ในโค้ดตัวอย่างไม่มี เลยคิดว่าเป็นข้อทักท้วงที่ถูกต้อง แต่ถ้าเพิ่มแค่อย่างเดียวก็น่าจะทำให้ปลอดภัยอย่างสมเหตุสมผลได้พอสมควร
      อย่างไรก็ตาม ผมกังวลว่าแค่ ละครความปลอดภัย แบบนี้อาจเพียงพอให้ผ่านกฎหมายและข้อบังคับด้านความเป็นส่วนตัวหลายฉบับได้
  • ดูฉลาดดี แต่ body:hover มีแนวโน้มจะพลาด ผู้ใช้ที่ใช้แต่คีย์บอร์ด และ user agent ที่ไม่ใช้อุปกรณ์ชี้ตำแหน่ง กล่าวคือผู้ใช้เทคโนโลยีช่วยเหลือ แทบจะทั้งหมด
    แม้กลุ่มเหล่านี้อาจเป็นกลุ่มชายขอบ แต่การเห็นว่าพวกเขาถูกกีดกันไม่ทางใดก็ทางหนึ่งเป็นสัญญาณที่แย่มากเสมอ
    ผมไม่แน่ใจ และค่อนข้างสงสัยด้วยว่า CSS พื้นฐานล้วน ๆ จะมีวิธีตรวจจับได้อย่างเชื่อถือได้ 100% ในทุก user agent ว่า “ผู้ใช้จริงกำลังอ่านบทความนี้อยู่” แล้วส่ง HTTP request หรือไม่ บางตัวอาจไม่รองรับ CSS เลย หรืออาจปิดการโหลดภาพตกแต่งของ CSS ไว้
    selector สมัยใหม่ที่อาจช่วยได้คือ :root:focus-within แต่ผู้ใช้ต้องโฟกัสไปที่องค์ประกอบที่โต้ตอบได้จริง และ user agent ทั้งหมดก็ไม่ได้รับประกันเรื่องนี้ แม้แต่ @scroll-timeline ซึ่งเป็นแอนิเมชันผูกกับการเลื่อนหน้าจอระดับล้ำสมัย ก็ยังมีแนวโน้มที่จะพลาดผู้อ่านอักษรเบรลล์อยู่ดี

    • ชายขอบเหรอ? มันไม่ได้กระทบโทรศัพท์กับแท็บเล็ตที่ไม่รองรับ :hover ซึ่งก็คือ มากกว่า 50% ของ user agent หรือ? แน่นอนว่าในกรณีที่ไม่ได้เสียบเมาส์
    • ถ้าดูตามวิธีที่เขียนไว้ บนอุปกรณ์ที่มี pointer จะขึ้นกับตำแหน่ง pointer ถ้า pointer อยู่ใน พื้นที่ 760px ตรงกลางก็จะทำงาน แต่ถ้าอยู่นอกนั้นก็ไม่ทำงาน
      พื้นที่นี้คือความกว้างที่รวมคอลัมน์เนื้อหากับ padding ข้างละ 20px ดังนั้นผู้ใช้คีย์บอร์ดบางส่วนจะถูกจับได้ ส่วนผู้ใช้เมาส์บางส่วน โดยเฉพาะผู้ใช้ viewport ขนาดใหญ่ จะไม่ถูกจับได้
  • ที่บอกว่า “ไม่ใช่แค่สิ่งแย่ ๆ อย่าง Google Analytics แต่ Fathom กับ Plausible ก็มีปัญหาในการบันทึกกิจกรรมบนเบราว์เซอร์ที่บล็อกโฆษณา” ผมมองว่าเป็นเพราะพวกเขาพยายามเอาตัวรอดอยู่ใน ดินแดนรกร้างอันเป็นพิษ โดยแท้
    ผู้ใช้อย่างเราเบื่อแนวคิดทั้งหมดนี้แล้ว และถ้า analytics แบบ CSS ได้รับความนิยม ผมคิดว่าก็จะมีความพยายามหาทางเลี่ยงมันเช่นกัน

    • ทำไมถึงเป็นแบบนั้น?
      ผมปลดบล็อก Piwik/Matomo, Plausible, Fathom ใน uBlock ด้วยตัวเอง ผมไม่เห็นว่าสิ่งที่พวกเขาติดตามและวิธีติดตามนั้นเป็นอันตราย และมันให้ข้อมูลที่เป็นประโยชน์แก่ผู้ดูแลไซต์เพื่อ “ปรับปรุงบริการ”
      ตัวอย่างเช่น Plausible เก็บข้อมูลเกี่ยวกับผมน้อยกว่าล็อก nginx หรือ Apache ทั่วไปเสียอีก ในมุมของบล็อกเกอร์ การเห็นว่าบทความถูกโพสต์ขึ้น HN หรือไม่ ถูกลิงก์จากที่ไหนสักแห่งหรือไม่ คอนเทนต์แบบไหนถูกมองว่ามีคุณค่าและแบบไหนถูกมองข้าม เป็นเรื่องสำคัญ เพราะจะได้เขียนสิ่งที่คนอยากอ่านจริง ๆ และกระจายผ่านช่องทางที่รับรู้ได้จริง
    • การเอา access.log ของเว็บเซิร์ฟเวอร์ไปใส่ในบริการวิเคราะห์ไม่ได้ป้องกันอะไรเลย
      กลับกัน ตัวเลขอาจพองขึ้นได้ เพราะแทบเป็นไปไม่ได้เลยที่จะกรอง ทราฟฟิกบอท ทั้งหมดโดยดูแค่ user agent
    • สิ่งที่ทำให้เว็บรู้สึกเหมือนดินแดนรกร้างอันเป็นพิษสำหรับผมคือโฆษณาสารพัดแบบ ส่วนการติดตามเป็นปัญหาที่ละเอียดอ่อนกว่านั้นมาก โดยความเสียหายในระยะยาวคืออาจมีการสร้าง ดิจิทัลทวิน ที่ใช้ทดลองเพื่อหาวิธีที่ดีที่สุดในการชักจูงผม
      ผมไม่รู้ว่าจริง ๆ แล้วมีคนกลัวเรื่องนี้มากแค่ไหน ปฏิกิริยาน่าจะแตกต่างกันตั้งแต่ “ใช่ น่าขนลุก” ไปจนถึง “ไร้สาระ นั่นมันแค่ไซไฟ”
    • นึกถึง uMatrix ที่เคยบล็อกได้ถึงขั้นการโหลด CSS
    • วิธีนี้ไม่ได้บล็อกยากกว่าวิธี JavaScript สุดท้ายก็แค่บล็อกคำขอที่ไปยัง รูปแบบ URL บางอย่างเท่านั้น
  • เรื่องนี้เป็นที่รู้จักกันมาหลายสิบปีแล้วในชื่อ พิกเซลติดตาม

    • ใช้ในอีเมลด้วย การโหลดรูปโปร่งใส 1x1 แน่นอนกว่าการทริกเกอร์อีเวนต์ hover แต่ ad blocker มักบล็อกรูปแบบนั้นบ่อย
    • ใช่ เพียงแต่ถ้าทำด้วย CSS ก็มีแง่มุมที่น่าสนใจอยู่บ้าง การใช้ :hover จะช่วยกรองบอทที่ไม่ได้ใช้ WebDriver แบบเต็มรูปแบบออกไปได้ ซึ่งก็คือบอทส่วนใหญ่
      ในบางแง่ วิธีโหลดไฟล์ .css ที่แทบจะว่างเปล่าผ่าน @import พร้อมกับ supports อาจดีกว่าด้วยซ้ำ ad blocker จับพิกเซลติดตามโปร่งใส 1px ได้เก่งมาก แต่มีแนวโน้มจะบล็อกไฟล์ .css น้อยกว่าเพื่อไม่ให้เลย์เอาต์พัง อย่างไรก็ตาม กรณีนี้ก็จะเสียข้อดีอันชาญฉลาดของ :hover ไป
  • เป็นคำถามที่สงสัยจริง ๆ แต่กลัวว่าจะอ่านแล้วเหมือนความเห็นที่ไม่ให้ค่า เป้าหมายของการเก็บข้อมูลวิเคราะห์บน บล็อกส่วนตัวที่ไม่ใช่เชิงพาณิชย์ แบบที่ดูเหมือน Bearblog คืออะไร?

    • ในฐานะคนเขียนที่ทำบล็อกมาอย่างต่อเนื่องตั้งแต่ราวปี 2000 และสนใจ “สถิติ” มากมาตลอด ผมพอจะตอบได้
      เหตุผลหลักที่สนใจ analytics คือเพื่อดูว่าบทความถูกอ่านหรือไม่ ภายนอก และในบางแง่ก็เพราะความหลงตัวเอง แต่จริง ๆ แล้วมันเกี่ยวกับ ความเชื่อมโยงระหว่างผู้เขียนกับผู้อ่าน ผมอยากรู้จริง ๆ ว่าผู้อ่านตอบสนองต่ออะไร และอยากมอบสิ่งนั้นให้มากขึ้น “สิ่งนั้น” อาจเป็นหัวข้อ น้ำเสียง หรือความยาวก็ได้ มันช่วยปรับแต่งเนื้อหาให้เหมาะกับผู้อ่านของผม ท้ายที่สุดแล้ว ผมเขียนได้สิบสองหัวข้อในยี่สิบสี่วิธี แน่นอนว่าผมเขียนสิ่งที่ชอบ แต่ก็ปรับให้สะท้อนกับผู้อ่านได้ดีขึ้น
      ในความหมายนี้ analytics ก็เป็นวิธีทำความรู้จักผู้อ่านด้วย สำหรับบล็อกที่มี engagement สูง analytics ให้ภาพร่างบุคลิกที่เลือนรางของผู้อ่าน ไม่ใช่แค่เห็นว่าพวกเขาชอบอะไร แต่ยังเห็นว่าชอบเมื่อไรด้วย เห็นได้ว่าอ่านเป็นอย่างแรกในตอนเช้า อ่านตอนพักเที่ยง หรืออ่านดึก ๆ ซึ่งช่วยในการตัดสินใจว่าจะโพสต์ในเวลาหนึ่ง ๆ หรือช่วยยืนยันการตัดสินใจนั้น แน่นอนว่าทั้งหมดเป็นข้อมูลที่เลือนราง แต่ช่วยให้เชื่อมโยงกับผู้อ่านได้อย่างกระตือรือร้นขึ้นจริง ๆ
    • เพราะ ลูปฟีดแบ็ก ต่างหาก ตรงข้ามกับที่หลายคนคิด analytics ไม่ได้มีไว้เพื่อโฆษณาหรือขายข้อมูลเท่านั้น แต่คือการวิเคราะห์ประสิทธิภาพของไซต์และคอนเทนต์
      แน่นอนว่ามันใช้กับโฆษณาได้และถูกใช้ในทางที่ผิดได้ แต่ถ้าผมต้องการฟีดแบ็กต่อสิ่งที่ทำอยู่ มันก็จำเป็น
      ไม่ว่าไซต์จะมีคนอ่าน 12 คนหรือ 12,000 คน มันอาจไม่มีมูลค่าทางการเงินก็ได้ แต่ในมุมส่วนตัว การรู้ว่าผู้คนอยากอ่านอะไรจากผมเป็นเรื่องดี ทำให้รู้สึกว่าเวลาที่ใช้เขียนถูกใช้ไปอย่างคุ้มค่า และถ้าต้องการก็ปรับไปในทางที่ได้รับความนิยมมากขึ้นได้
    • อาจเป็นความอยากรู้อยากเห็นก็ได้ ผมอยากรู้ว่ามีใครอ่านสิ่งที่ผมเขียนไหม การรู้ว่าผู้คนสนใจอะไรก็มีประโยชน์
      แม้จะเป็นบล็อกเกอร์ส่วนตัว ก็อาจอยากปรับคอนเทนต์ให้เข้ากับผู้อ่าน การรู้ว่าบทความหัวข้อหนึ่งมีคนอ่าน 500 คน แต่อีกหัวข้อมีแค่ 3 คนอ่าน เป็นเรื่องดี
  • ต้นปีนี้ผมเคยลองทำอะไรแบบนี้ แต่หมดแรงจูงใจระหว่างทำเว็บ UI วิธีของผมไม่ใช่ CSS แต่เป็นการโหลด รูปภาพปลอม ผ่านแท็กแบบง่าย ๆ
    https://github.com/nolytics

  • ทำไมไม่ดึงข้อมูลนี้จาก HTTP server ไปเลย?

    • ในบล็อกอธิบายไว้แบบนี้
      “ตัวเลือกในการ parse server log มีอยู่เสมอ และพอจะทำให้เห็นคร่าว ๆ ว่าทราฟฟิกแบบไหนเข้าถึงเซิร์ฟเวอร์ แต่โดยทั่วไปทราฟฟิกทั้งหมดของเซิร์ฟเวอร์จะดูเหมือนกันหมด ในทางเทคนิค บอทควรมี user agent ที่ระบุว่าตัวเองเป็นบอท แต่เพราะพวกมันพยายามกวาดข้อมูลให้เหมือน ‘คน’ ที่ใช้เบราว์เซอร์ จึงแทบไม่ระบุตัวเองแบบนั้น โดยพื้นฐานแล้ว ถ้าใช้แค่ server log ในการวิเคราะห์ คุณจะเห็นทราฟฟิกบิดเบี้ยว เพราะมีทั้ง crawler ของเสิร์ชเอนจิน, scraper และตอนนี้ยังมี parser ที่ใช้ GPT อีกมากมาย”
    • บอทปนเข้ามาทั้งหมด
    • ถ้า运行แบบ serverless ก็ทำได้ยาก
  • ข้อมูลวิเคราะห์เก็บไว้อย่างไร?
    สมมติว่ามีไซต์อีคอมเมิร์ซและมีสินค้าที่ต้องการขาย นอกจาก analytics แล้ว ก็ตัดสินใจบันทึกพฤติกรรมบางอย่างเอง เช่น การเข้าชมหน้ารายละเอียดสินค้าในสถานะที่ล็อกอินอยู่ ดังนั้นจึงต้องการเก็บสิ่งต่าง ๆ เช่น ID ผู้ใช้, ID สินค้า, timestamp
    แล้วในทางปฏิบัติควรเก็บอย่างไร? ตอนแรกคิดแบบง่าย ๆ ว่าใส่ลงตารางก็พอ DBA ถามว่าต้องใช้ข้อมูลนานแค่ไหน และตอบไปว่าอย่างน้อยหนึ่งเดือน จากนั้นเขาก็บอกว่าโอเค และดูเหมือนว่าอาจตั้งงานให้ย้ายข้อมูลที่เก่ากว่านั้นไปยังตารางอื่นไว้แล้ว
    ในทางปฏิบัติแล้ว log แบบนี้เก็บกันอย่างไร และเก็บไว้นานแค่ไหน?

    • ถ้าไม่ได้มีสเกลใหญ่มาก การใส่ไว้ใน ตาราง Postgres ก็ใช้ได้อย่างสมบูรณ์ แม้สเกลจะใหญ่ ก็สามารถ partition ตารางตามวันที่หรือแอตทริบิวต์อื่นที่เหมาะสม เพื่อไม่ต้องจัดการกับ index ขนาดมหึมาได้
      เคยทำแบบนี้มาก่อน และจนกว่าจะถึงประมาณ 1 พันล้านแถวก็ยังไม่จำเป็นต้องคิดเรื่อง partitioning ด้วยซ้ำ ถึงอย่างนั้นก็ควรทำ partitioning ให้เร็วกว่านั้น ประสบการณ์ครั้งนั้นไม่สนุกเลย
    • ฐานข้อมูลสำหรับ analytics จะดีกว่า เช่น ClickHouse หรือ BigQuery
      ทำ aggregation ได้เร็วกว่ามาก และจัดการกับคอลัมน์จำนวนมากที่มีข้อมูลกระจัดกระจายได้ดี เช่น event paid มีแอตทริบิวต์ amount ส่วน event page_view มีแอตทริบิวต์ url เป็นต้น
    • เก็บ ข้อมูล 13 ปี ไว้ใน MySQL มีผู้เข้าชมปีละ 5 ล้านคน การ query ในนั้นทรมานมาก เลยเก็บสำเนาไว้ใน ClickHouse ด้วย ClickHouse query ได้สะดวกมากจริง ๆ
    • ใช้ Postgres กับ TimescaleDB ถ้าไซต์อีคอมเมิร์ซไม่ได้มีสเกลระดับ amazon.com ก็ทำงานได้ดี
      ข้อดีของ TimescaleDB คือมันจัดการสร้าง materialized view สำหรับ aggregation ที่สนใจ เช่น จำนวนการดูสินค้าต่อชั่วโมง ให้เอง หากมี event จำนวนมากและไม่อยากให้ฐานข้อมูลใหญ่เกินไป ก็เลือก “ทิ้ง” ตัว event เอง แล้วเหลือไว้เฉพาะ aggregation ได้
    • ClickHouse