Trenutno skoro svaka kompanija na svijetu prikuplja statistiku o radnjama korisnika na web resursu. Motivacija je jasna - kompanije žele znati kako se njihov proizvod/web stranica koristi i bolje razumjeti svoje korisnike. Naravno, na tržištu postoji veliki broj alata za rješavanje ovog problema – od analitičkih sistema koji daju podatke u obliku kontrolne table i grafikona (npr.
Ali pronašli smo problem koji još nije riješen. Tako je rođen
Zašto bismo trebali razviti 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, identifikaciju zavisnosti itd. Primijetili smo da mnogi korisnici koriste našu platformu za analizu podataka posebno Google Analytics (u daljem tekstu GA). Razgovarali smo s nekim korisnicima i saznali da su im potrebni analitički podaci za njihov proizvod koje dobijaju putem GA, ali
Instalirali su Segment javascript piksel 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 MTU (mjesečno praćenih korisnika), onda morate plaćati ~1,000 $ mjesečno blagajni. Postojao je i treći problem - neke ekstenzije pretraživača (kao što je AdBlock) blokirale su prikupljanje analitike jer... http zahtjevi iz pretraživača su poslani na domene GA i segmenta. Na osnovu želja naših klijenata kreirali smo uslugu analitike koja prikuplja kompletan set podataka (bez uzorkovanja), besplatna je i može raditi na vlastitoj infrastrukturi.
Kako servis funkcioniše
Servis se sastoji iz tri dela: javascript piksela (koji smo kasnije prepisali u kucani tekst), serverski deo je implementiran u GO jeziku, a planirano je da se kao interna baza podataka koriste Redshift i BigQuery (kasnije su dodali podršku za Postgres, ClickHouse i Snowflake).
Odlučeno je da se struktura GA i Segment događaja ostavi nepromijenjena. Sve što je bilo potrebno je duplirati sve događaje iz web resursa gdje je piksel instaliran na naš backend. Kako se ispostavilo, to nije teško učiniti. Javascript piksel je nadjačao originalnu GA metodu biblioteke novom, koja je duplirala događaj u našem sistemu.
//'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);
});
});
}
Sa segmentnim pikselom sve je jednostavnije; on ima međuverske metode, od kojih smo jednu koristili.
//'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.');
}
Pored kopiranja događaja, dodali smo i mogućnost slanja proizvoljnog json-a:
//Отправка событий с произвольным 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'
});
Dalje, hajde da pričamo o serverskom delu. Backend bi trebao prihvatiti http zahtjeve, ispuniti ih dodatnim informacijama, na primjer, geografskim 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 ponovljena polja. Također je moguće promijeniti nazive polja ili ih izbrisati korištenjem opcijskih pravila mapiranja. Oni vam omogućavaju da promijenite šemu podataka ako je potrebno ili pretvorite jedan tip podataka u drugi. Na primjer, ako json polje sadrži niz s vremenskom oznakom (field_3_sub_field_1_sub_sub_field_1 iz gornjeg primjera), tada da biste kreirali polje u bazi podataka s tipom vremenske oznake, trebate napisati pravilo mapiranja u konfiguraciji. Drugim riječima, tip podataka polja je određen najprije json vrijednošću, a zatim se primjenjuje pravilo određivanja tipa (ako je konfigurirano). Identificirali smo 4 glavna tipa podataka: STRING, FLOAT64, INT64 i TIMESTAMP. Pravila mapiranja i ubacivanja tipova 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 tipa podataka:
- pretvoriti json strukturu u ravnu strukturu
- određivanje tipa podataka polja po vrijednostima
- primjena pravila mapiranja i tipova
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"
}
}
dobiće se šema 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 smatrali da bi korisnik trebao biti u mogućnosti da konfigurira particioniranje ili podjelu podataka u bazi podataka prema drugim kriterijima i implementirali smo mogućnost postavljanja imena tablice sa konstantom ili
tableName: '{{.product_type}}_{{._timestamp.Format "2006_01"}}'
Međutim, struktura dolaznih događaja može se promijeniti u vremenu izvođenja. Implementirali smo algoritam za provjeru razlike između strukture postojeće tabele i strukture dolaznog događaja. Ako se pronađe razlika, tabela će biti ažurirana novim poljima. Da biste to učinili, koristite SQL upit zakrpe:
#Пример для Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying
arhitektura
Zašto trebate pisati događaje u sistem datoteka, a ne samo ih pisati direktno u bazu podataka? Baze podataka ne rade uvijek dobro kada se bave velikim brojem umetanja (
Open Source i planovi za budućnost
U nekom trenutku usluga je počela izgledati kao punopravni proizvod i odlučili smo da je pustimo na Open Source. Trenutno su implementirane integracije sa Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake. Sve integracije podržavaju i paketni i streaming način učitavanja podataka. Dodata podrška za zahtjeve putem API-ja.
Trenutna šema integracije izgleda ovako:
Iako se usluga može koristiti samostalno (na primjer korištenjem Dockera), imamo i mi
→
→
→
Bit će nam drago ako EventNative pomogne u rješavanju vaših problema!
Samo registrovani korisnici mogu učestvovati u anketi.
Koji sistem prikupljanja statistike se koristi u vašoj kompaniji?
-
48,0%Google Analytics12
-
4,0%Segment1
-
16,0%Još jedan (napišite u komentarima)4
-
32,0%Implementirao vaš servis8
Glasalo je 25 korisnika. Uzdržano je bilo 6 korisnika.
izvor: www.habr.com