Trenutno gotovo svaka tvrtka u svijetu prikuplja statistiku o radnjama korisnika na web resursu. Motivacija je jasna – tvrtke žele znati kako se njihov proizvod/web stranica koristi i bolje razumjeti svoje korisnike. Naravno, na tržištu postoji velik broj alata za rješavanje ovog problema – od analitičkih sustava koji daju podatke u obliku nadzornih ploča i grafikona (npr.
Ali pronašli smo problem koji još nije riješen. Tako je rođeno
Zašto bismo trebali razvijati vlastitu uslugu?
Bile su devedesete, preživljavali smo kako smo mogli. 2019. razvili smo API First Customer Data Platform kSense, što je omogućilo agregiranje podataka iz različitih izvora (Facebook oglasi, Stripe, Salesforce, Google play, Google Analytics itd.) za praktičniju analizu podataka, prepoznavanje ovisnosti itd. Primijetili smo da mnogi korisnici koriste našu platformu za analizu podataka posebno Google Analytics (u daljnjem tekstu GA). Razgovarali smo s nekim korisnicima i otkrili da im trebaju analitički podaci za njihov proizvod koje dobivaju pomoću GA-a, ali
Instalirali su Segment javascript pixel na svoj web resurs i podaci o ponašanju njihovih korisnika su učitani u navedenu bazu podataka (na primjer Postgres). Ali Segment ima i svoju lošu stranu - cijenu. Na primjer, ako web resurs ima 90,000 1,000 MTU (mjesečno praćenih korisnika), tada trebate platiti ~XNUMX $ mjesečno na blagajni. Postojao je i treći problem - neka proširenja preglednika (kao što je AdBlock) blokirala su prikupljanje analitike jer... http zahtjevi iz preglednika poslani su na domene GA i Segment. Na temelju želja naših klijenata kreirali smo analitičku uslugu koja prikuplja kompletan skup podataka (bez uzorkovanja), besplatna je i može raditi na vlastitoj infrastrukturi.
Kako usluga radi
Servis se sastoji od tri dijela: javascript piksel (koji smo kasnije prepisali u tipkalo), serverski dio je implementiran u GO jeziku, a planirano je korištenje Redshifta i BigQueryja kao interne baze podataka (kasnije su dodali podršku za Postgres, ClickHouse i Snowflake).
Odlučeno je ostaviti nepromijenjenu strukturu GA i Segment događaja. Sve što je bilo potrebno je duplicirati sve događaje s web resursa na kojem je piksel instaliran na našu pozadinu. Kako se pokazalo, to nije teško učiniti. Javascript piksel nadjačao je izvornu metodu biblioteke GA novom, koja je duplicirala događaj u našem sustavu.
//'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 sve je jednostavnije; ima metode međuprograma, od kojih smo mi koristili jednu.
//'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.');
}
Osim kopiranja događaja, dodali smo mogućnost slanja proizvoljnog jsona:
//Отправка событий с произвольным 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'
});
Zatim, razgovarajmo o poslužiteljskom dijelu. Pozadina bi trebala prihvatiti http zahtjeve, popuniti ih dodatnim informacijama, na primjer, zemljopisnim podacima (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"
}
Međutim, nizovi se trenutno jednostavno pretvaraju u nizove jer Ne podržavaju sve relacijske baze podataka polja koja se ponavljaju. Također je moguće promijeniti nazive polja ili ih izbrisati korištenjem opcijskih pravila mapiranja. Omogućuju vam promjenu podatkovne sheme ako je potrebno ili pretvaranje jedne vrste podataka u drugu. Na primjer, ako json polje sadrži niz s vremenskom oznakom (polje_3_podpolje_1_pod_podpolje_1 iz gornjeg primjera), tada da biste stvorili polje u bazi podataka s vrstom vremenske oznake, trebate napisati pravilo mapiranja u konfiguraciji. Drugim riječima, tip podataka polja prvo je određen json vrijednošću, a zatim se primjenjuje pravilo pretvaranja tipa (ako je konfigurirano). Identificirali smo 4 glavne vrste podataka: STRING, FLOAT64, INT64 i TIMESTAMP. Pravila preslikavanja i pretvaranja tipa izgledaju ovako:
rules:
- "/field_1/subfield_1 -> " #правило удаления поля
- "/field_2/subfield_1 -> /field_10/subfield_1" #правило переноса поля
- "/field_3/subfield_1/subsubfield_1 -> (timestamp) /field_20" #правило переноса поля и приведения типа
Algoritam za određivanje vrste podataka:
- pretvoriti json strukturu u ravnu strukturu
- određivanje vrste podataka polja po vrijednostima
- primjenom pravila preslikavanja i pretvaranja tipa
Zatim iz dolazne json strukture:
{
"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"
}
}
dobit će se shema podataka:
"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
Također smo mislili da bi korisnik trebao moći konfigurirati particioniranje ili podijeliti podatke u bazi podataka prema drugim kriterijima i implementirali smo mogućnost postavljanja naziva tablice s konstantom ili
tableName: '{{.product_type}}_{{._timestamp.Format "2006_01"}}'
Međutim, struktura dolaznih događaja može se promijeniti tijekom izvođenja. Implementirali smo algoritam za provjeru razlike između strukture postojeće tablice i strukture dolaznog događaja. Ako se pronađe razlika, tablica će se ažurirati novim poljima. Da biste to učinili, upotrijebite patch SQL upit:
#Пример для Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying
arhitektura
Zašto trebate pisati događaje u datotečni sustav, a ne samo ih pisati izravno u bazu podataka? Baze podataka ne rade uvijek dobro kada rade s velikim brojem umetaka (
Open Source i planovi za budućnost
U nekom je trenutku usluga počela izgledati kao potpuni proizvod i odlučili smo je objaviti u Open Sourceu. Trenutno su implementirane integracije s Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake. Sve integracije podržavaju skupne i strujne načine učitavanja podataka. Dodana podrška za zahtjeve putem API-ja.
Trenutna shema integracije izgleda ovako:
Iako se usluga može koristiti samostalno (na primjer pomoću Dockera), mi također imamo
→
→
→
Bit će nam drago ako EventNative pomogne u rješavanju vaših problema!
U anketi mogu sudjelovati samo registrirani korisnici.
Koji se sustav prikupljanja statistike koristi u vašoj tvrtki?
-
48,0%Google Analytics12
-
4,0%Segment1
-
16,0%Još jedno (napišite u komentarima)4
-
32,0%Implementirao svoju uslugu8
Glasovalo je 25 korisnika. Suzdržano je bilo 6 korisnika.
Izvor: www.habr.com