Trenutno skoraj vsako podjetje na svetu zbira statistične podatke o dejanjih uporabnikov na spletnem viru. Motivacija je jasna – podjetja želijo vedeti, kako se uporablja njihov izdelek/spletna stran in bolje razumeti svoje uporabnike. Seveda je na trgu ogromno orodij za reševanje te težave – od analitičnih sistemov, ki podajajo podatke v obliki nadzornih plošč in grafov (npr.
Vendar smo našli problem, ki še ni rešen. Tako se je rodilo
Zakaj bi morali razvijati lastno storitev?
Bila so devetdeseta leta, preživeli smo, kakor smo znali. 2019 smo razvili API First Customer Data Platform kSense, ki je omogočila agregacijo podatkov iz različnih virov (Facebook oglasi, Stripe, Salesforce, Google play, Google Analytics itd.) za bolj priročno analizo podatkov, prepoznavanje odvisnosti itd. Opazili smo, da veliko uporabnikov uporablja našo platformo za analizo podatkov, posebej Google Analytics (v nadaljevanju GA). Pogovarjali smo se z nekaterimi uporabniki in ugotovili, da potrebujejo analitične podatke za svoj izdelek, ki jih prejmejo z GA, vendar
Na svoj spletni vir so namestili piksel Segment javascript in podatke o vedenju njihovih uporabnikov so naložili v navedeno bazo podatkov (na primer Postgres). Ima pa Segment tudi svojo slabo stran - ceno. Na primer, če ima spletni vir 90,000 MTU (mesečno sledenih uporabnikov), potem morate blagajni plačati ~1,000 $ na mesec. Obstajala je tudi tretja težava - nekatere razširitve brskalnika (kot je AdBlock) so blokirale zbiranje analitike, ker... http zahteve iz brskalnika so bile poslane domeni GA in Segment. Na podlagi želja naših naročnikov smo izdelali analitično storitev, ki zbira celoten nabor podatkov (brez vzorčenja), je brezplačna in lahko deluje na lastni infrastrukturi.
Kako storitev deluje
Storitev je sestavljena iz treh delov: javascript pixel (ki smo ga kasneje prepisali v tipkopis), strežniški del je implementiran v jeziku GO, načrtovana pa je bila uporaba Redshift in BigQuery kot lastne podatkovne baze (kasneje so dodali podporo za Postgres, ClickHouse in Snowflake).
Odločeno je bilo, da ostane struktura dogodkov GA in segmenta nespremenjena. Vse, kar je bilo potrebno, je bilo podvojiti vse dogodke iz spletnega vira, kjer je nameščen piksel, v naše zaledje. Kot se je izkazalo, tega ni težko narediti. Piksel Javascript je preglasil izvirno metodo knjižnice GA z novo, ki je podvojila dogodek v naš sistem.
//'ga' - стандартное название переменной Google Analytics
if (window.ga) {
ga(tracker => {
var originalSendHitTask = tracker.get('sendHitTask');
tracker.set('sendHitTask', (model) => {
var payLoad = model.get('hitPayload');
//отправка оригинального события в GA
originalSendHitTask(model);
let jsonPayload = this.parseQuery(payLoad);
//отправка события в наш сервис
this.send3p('ga', jsonPayload);
});
});
}
S pikselom Segment je vse preprostejše; ima metode vmesne programske opreme, eno izmed njih smo uporabili.
//'analytics' - стандартное название переменной Segment
if (window.analytics) {
if (window.analytics.addSourceMiddleware) {
window.analytics.addSourceMiddleware(chain => {
try {
//дублирование события в наш сервис
this.send3p('ajs', chain.payload);
} catch (e) {
LOG.warn('Failed to send an event', e)
}
//отправка оригинального события в Segment
chain.next(chain.payload);
});
} else {
LOG.warn("Invalid interceptor state. Analytics js initialized, but not completely");
}
} else {
LOG.warn('Analytics.js listener is not set.');
}
Poleg kopiranja dogodkov smo dodali možnost pošiljanja poljubnih json:
//Отправка событий с произвольным json объектом
eventN.track('product_page_view', {
product_id: '1e48fb70-ef12-4ea9-ab10-fd0b910c49ce',
product_price: 399.99,
price_currency: 'USD'
product_release_start: '2020-09-25T12:38:27.763000Z'
});
Nato se pogovorimo o strežniškem delu. Zaledje bi moralo sprejemati zahteve http, jih napolniti z dodatnimi informacijami, na primer z geografskimi podatki (hvala
//входящий json
{
"field_1": {
"sub_field_1": "text1",
"sub_field_2": 100
},
"field_2": "text2",
"field_3": {
"sub_field_1": {
"sub_sub_field_1": "2020-09-25T12:38:27.763000Z"
}
}
}
//результат
{
"field_1_sub_field_1": "text1",
"field_1_sub_field_2": 100,
"field_2": "text2",
"field_3_sub_field_1_sub_sub_field_1": "2020-09-25T12:38:27.763000Z"
}
Vendar se nizi trenutno preprosto pretvorijo v nize, ker Vse relacijske baze podatkov ne podpirajo ponavljajočih se polj. Prav tako je mogoče spremeniti imena polj ali jih izbrisati z izbirnimi pravili preslikave. Omogočajo vam, da po potrebi spremenite podatkovno shemo ali pretvorite eno vrsto podatkov v drugo. Na primer, če polje json vsebuje niz s časovnim žigom (polje_3_podpolje_1_pod_podpolje_1 iz zgornjega primera), potem morate za ustvarjanje polja v bazi podatkov z vrsto časovnega žiga v konfiguracijo napisati pravilo preslikave. Z drugimi besedami, podatkovni tip polja je najprej določen z vrednostjo json, nato pa se uporabi pravilo za pretvorbo tipa (če je konfigurirano). Identificirali smo 4 glavne vrste podatkov: STRING, FLOAT64, INT64 in TIMESTAMP. Pravila za preslikavo in pretvorbo tipa izgledajo takole:
rules:
- "/field_1/subfield_1 -> " #правило удаления поля
- "/field_2/subfield_1 -> /field_10/subfield_1" #правило переноса поля
- "/field_3/subfield_1/subsubfield_1 -> (timestamp) /field_20" #правило переноса поля и приведения типа
Algoritem za določanje vrste podatkov:
- pretvori strukturo json v ravno strukturo
- določanje podatkovnega tipa polj po vrednostih
- uporaba pravil za preslikavo in ulivanje tipov
Nato iz dohodne strukture json:
{
"product_id": "1e48fb70-ef12-4ea9-ab10-fd0b910c49ce",
"product_price": 399.99,
"price_currency": "USD",
"product_type": "supplies",
"product_release_start": "2020-09-25T12:38:27.763000Z",
"images": {
"main": "picture1",
"sub": "picture2"
}
}
podatkovna shema bo pridobljena:
"product_id" character varying,
"product_price" numeric (38,18),
"price_currency" character varying,
"product_type" character varying,
"product_release_start" timestamp,
"images_main" character varying,
"images_sub" character varying
Pomislili smo tudi, da mora imeti uporabnik možnost konfiguriranja particioniranja ali razdelitve podatkov v bazi podatkov po drugih kriterijih in implementirali možnost nastavitve imena tabele s konstanto oz.
tableName: '{{.product_type}}_{{._timestamp.Format "2006_01"}}'
Vendar se lahko struktura dohodnih dogodkov med izvajanjem spremeni. Implementirali smo algoritem za preverjanje razlike med strukturo obstoječe tabele in strukturo dohodnega dogodka. Če se ugotovi razlika, bo tabela posodobljena z novimi polji. Če želite to narediti, uporabite poizvedbo SQL za popravek:
#Пример для Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying
arhitektura
Zakaj morate dogodke pisati v datotečni sistem in ne samo neposredno v bazo podatkov? Baze podatkov ne delujejo vedno dobro, ko imajo opravka z velikim številom vstavkov (
Odprta koda in načrti za prihodnost
Na neki točki je storitev začela izgledati kot polnopravni izdelek in odločili smo se, da jo objavimo v odprtokodni različici. Trenutno so implementirane integracije s Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake. Vse integracije podpirajo paketni in pretočni način nalaganja podatkov. Dodana podpora za zahteve prek API-ja.
Trenutna integracijska shema izgleda takole:
Čeprav je storitev mogoče uporabljati samostojno (na primer z uporabo Dockerja), jo tudi imamo
→
→
→
Veseli bomo, če vam bo EventNative pomagal rešiti težave!
V anketi lahko sodelujejo samo registrirani uporabniki.
Kakšen sistem zbiranja statistike uporabljate v vašem podjetju?
-
48,0%Google Analytics12
-
4,0%Segment1
-
16,0%Še en (napišite v komentarje)4
-
32,0%Implementirali vašo storitev8
Glasovalo je 25 uporabnikov. 6 uporabnikov se je vzdržalo.
Vir: www.habr.com