Tans versamel byna elke maatskappy in die wêreld statistieke oor gebruikersaksies op 'n webhulpbron. Die motivering is duidelik – maatskappye wil weet hoe hul produk/webwerf gebruik word en hul gebruikers beter verstaan. Natuurlik is daar 'n groot aantal instrumente op die mark om hierdie probleem op te los - van ontledingstelsels wat data in die vorm van dashboards en grafieke verskaf (byvoorbeeld
Maar ons het 'n probleem gevind wat nog nie opgelos is nie. So is gebore
Hoekom moet ons ons eie diens ontwikkel?
Dit was die negentigerjare, ons het oorleef so goed ons kon. 2019 het ons die API First Customer Data Platform ontwikkel kSense, wat dit moontlik gemaak het om data uit verskillende bronne (Facebook-advertensies, Stripe, Salesforce, Google play, Google Analytics, ens.) te versamel vir meer gerieflike data-analise, identifisering van afhanklikhede, ens. Ons het opgemerk dat baie gebruikers ons platform gebruik vir data-analise spesifiek Google Analytics (hierna GA). Ons het met 'n paar gebruikers gepraat en uitgevind dat hulle die ontledingsdata benodig vir hul produk wat hulle met GA ontvang, maar
Hulle het 'n Segment-javascript-pixel op hul webhulpbron geïnstalleer en data oor die gedrag van hul gebruikers is in die gespesifiseerde databasis gelaai (byvoorbeeld Postgres). Maar Segment het ook sy nadeel - die prys. Byvoorbeeld, as 'n webhulpbron 90,000 1,000 MTU (maandelikse nagespoorde gebruikers) het, moet jy ~XNUMX XNUMX $ per maand aan die kassier betaal. Daar was ook 'n derde probleem - sommige blaaieruitbreidings (soos AdBlock) het die versameling van ontledings geblokkeer omdat... http-versoeke vanaf die blaaier is na die GA- en Segment-domeine gestuur. Gebaseer op die wense van ons kliënte, het ons 'n ontledingsdiens geskep wat 'n volledige stel data insamel (sonder steekproefneming), gratis is en op ons eie infrastruktuur kan werk.
Hoe die diens werk
Die diens bestaan uit drie dele: 'n javascript-pixel (wat ons later in tikskrif herskryf het), die bedienergedeelte is in die GO-taal geïmplementeer, en daar is beplan om Redshift en BigQuery as 'n interne databasis te gebruik (later het hulle ondersteuning bygevoeg vir Postgres, ClickHouse en Snowflake).
Daar is besluit om die struktuur van die GA en Segment-gebeure onveranderd te laat. Al wat nodig was, was om alle gebeure van die webhulpbron waar die pixel geïnstalleer is na ons agterkant te dupliseer. Soos dit blyk, is dit nie moeilik om te doen nie. Die Javascript-pixel het die oorspronklike GA-biblioteekmetode met 'n nuwe een vervang, wat die gebeurtenis in ons stelsel gedupliseer het.
//'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);
});
});
}
Met die Segment-pixel is alles eenvoudiger; dit het middelware-metodes, waarvan ons een gebruik het.
//'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.');
}
Benewens die kopiëring van gebeure, het ons die vermoë bygevoeg om arbitrêre json te stuur:
//Отправка событий с произвольным 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'
});
Kom ons praat dan oor die bedienerdeel. Die agterkant moet http-versoeke aanvaar, vul dit met bykomende inligting, byvoorbeeld geo-data (dankie
//входящий 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"
}
Skikkings word egter tans bloot na snare omgeskakel omdat Nie alle relasionele databasisse ondersteun herhaalde velde nie. Dit is ook moontlik om veldname te verander of dit uit te vee deur opsionele karteringreëls te gebruik. Hulle laat jou toe om die dataskema te verander indien nodig of een datatipe na 'n ander om te skakel. Byvoorbeeld, as 'n json-veld 'n string met tydstempel (field_3_sub_field_1_sub_sub_field_1 uit die voorbeeld hierbo), dan moet jy 'n karteringreël in die konfigurasie skryf om 'n veld in die databasis met die tydstempeltipe te skep. Met ander woorde, die datatipe van die veld word eers deur die json-waarde bepaal, en dan word die tipe-uitsaaireël (indien opgestel) toegepas. Ons het 4 hoofdatatipes geïdentifiseer: STRING, FLOAT64, INT64 en TIMESTAMP. Die kartering en tipe uitsaaireëls lyk soos volg:
rules:
- "/field_1/subfield_1 -> " #правило удаления поля
- "/field_2/subfield_1 -> /field_10/subfield_1" #правило переноса поля
- "/field_3/subfield_1/subsubfield_1 -> (timestamp) /field_20" #правило переноса поля и приведения типа
Algoritme vir die bepaling van die datatipe:
- omskep json-struktuur na plat struktuur
- bepaling van die datatipe velde deur waardes
- die toepassing van kartering en tipe gietreëls
Dan vanaf die inkomende json-struktuur:
{
"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"
}
}
die dataskema sal verkry word:
"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
Ons het ook gedink dat die gebruiker in staat moet wees om partisionering te konfigureer of data in die databasis te verdeel volgens ander kriteria en het die vermoë geïmplementeer om die tabelnaam met 'n konstante of
tableName: '{{.product_type}}_{{._timestamp.Format "2006_01"}}'
Die struktuur van inkomende gebeurtenisse kan egter tydens looptyd verander. Ons het 'n algoritme geïmplementeer om die verskil tussen die struktuur van 'n bestaande tabel en die struktuur van 'n inkomende gebeurtenis na te gaan. As 'n verskil gevind word, sal die tabel opgedateer word met nuwe velde. Om dit te doen, gebruik die pleister SQL-navraag:
#Пример для Postgres
ALTER TABLE "schema"."table" ADD COLUMN new_column character varying
Argitektuur
Hoekom moet jy gebeure na die lêerstelsel skryf, en nie net direk na die databasis skryf nie? Databasisse presteer nie altyd goed wanneer groot getalle insetsels hanteer word nie (
Oopbron en planne vir die toekoms
Op 'n stadium het die diens soos 'n volwaardige produk begin lyk en ons het besluit om dit na Open Source vry te stel. Tans is integrasies met Postgres, ClickHouse, BigQuery, Redshift, S3, Snowflake geïmplementeer. Alle integrasies ondersteun beide bondel- en stroommodusse van data-laai. Bygevoeg ondersteuning vir versoeke via API.
Die huidige integrasieskema lyk soos volg:
Alhoewel die diens onafhanklik gebruik kan word (byvoorbeeld met behulp van Docker), het ons ook
→
→
→
Ons sal bly wees as EventNative jou probleme help oplos!
Slegs geregistreerde gebruikers kan aan die opname deelneem.
Watter statistiek-insamelingstelsel word in jou maatskappy gebruik?
-
48,0%Google Analytics 12
-
4,0%Segment 1
-
16,0%Nog een (skryf in die kommentaar)4
-
32,0%Het u diens geïmplementeer8
25 gebruikers het gestem. 6 gebruikers het buite stemming gebly.
Bron: will.com