clickSomo

Contacten & toestemming

Een lijst die je kunt verdedigen, niet zomaar een lijst die je hebt

Iedereen kan tienduizend e-mailadressen bewaren. De vraag die er toe doet — de vraag die een toezichthouder, een provider en je eigen geweten elk in iets andere woorden stellen — is waar elk adres vandaan komt en op welke grondslag je erheen mag schrijven. ClickSomo maakt daarvan een opgeslagen feit in plaats van iets dat je zelf zou moeten reconstrueren.

Identiteit is het e-mailadres

Eén contact per adres per project, afgedwongen door de database in plaats van door hoopvolle veronderstelling. Adressen worden genormaliseerd bij het wegschrijven, nooit bij het lezen — normaliseer je bij het lezen, dan is de beperking een versiering die zowel Anna@ als anna@ binnenlaat.

Telefoonnummers worden in E.164 opgeslagen als ze bestaan, maar een telefoonnummer is een attribuut, geen identiteit. Er is geen identiteitsresolutiegrafiek, geen samenvoegprotocol en geen audit trail van samenvoegingen, want elk contact hier komt binnen via een kanaal dat al een adres heeft: een import, een formulier, een inschrijving, of je eigen code.

De naam wordt als geheel opgeslagen

display_name wordt exact bewaard zoals die is opgegeven en wordt nooit in delen gesplitst. Namen splitsen is een foutenfabriek — "van der Berg", "Kim Min-jun", mononiemen, titels, en elke naamvolgorde die niet Angelsaksisch is — en een verkeerde splitsing verschijnt in een merge-tag als "Beste van,", wat erger is dan helemaal geen personalisatie.

Gestructureerde delen bestaan alleen voor bronnen die ze al gescheiden aanleveren. Niets leidt ze af. En een naam die iemand zelf heeft getypt wordt nooit overschreven door een latere CSV die toevallig iets anders zag, want last-write-wins laat de slordigste import winnen.

Eén contactWat er wordt bewaard
  • 1IdentiteitE-mail, genormaliseerd. Uniek binnen het project.
  • 2NaamAls geheel opgeslagen. first_name wordt bij het renderen afgeleid, nooit opgeslagen.
  • 3AttributenAlles wat je wilt, als JSON. Van jou, en interpoleerbaar als attrs.*.
  • 4Tags en lijstenTags zijn first class en leven in één opslag; lijsten zijn expliciet lidmaatschap.
  • 5ToestemmingEén rij per kanaal, met een wettelijke grondslag en het bewijs daarvan.
  • 6EvenementenEen append-only log van alles wat deze persoon heeft gedaan. De tabel waar het product op rust.
  • ×NooitGeen wachtwoord, geen hash, geen sessie, geen API-sleutel. Een kolom die iemand authenticeert zou een incident zijn, geen feature.

Afgebakend tot tenant én project

Het toestemmingsregister

Afwezigheid is geen toestemming

Eén rij per contact per kanaal — e-mail, SMS, brief, push — elk met een status, een wettelijke grondslag, een bron, het bewijs, de tijdstempels en de jurisdictie. Een contact zonder grondslagrij voor een kanaal kan op dat kanaal niets ontvangen. Niet "wordt gemarkeerd". Kan niet.

consent

Iemand heeft er actief om gevraagd. Een formulierinzending met de bewijslast opgeslagen, een double opt-in, een vinkje dat de persoon zelf heeft gezet. Dit is de sterkste basis en de enige die een formulier kan opleveren.

legitimate_interest

Het beste wat een CSV-import kan worden. Een spreadsheet kan zich niet herinneren dat iemand ergens mee akkoord is gegaan, dus het mag nooit beweren dat dat zo is — en hetzelfde bestand opnieuw uploaden maakt het niet beter.

contract

Je schrijft ze omdat jullie allebei partij zijn bij iets. De servicemelding, de verlengingsherinnering, het ding waar ze geïrriteerd zouden zijn als ze het niet zouden ontvangen.

Voordat een campagne verstuurt, zie je de basisverdeling van het publiek: hoeveel van deze mensen hebben erom gevraagd, hoeveel je bereikt onder gerechtvaardigd belang, en hoeveel er staan vanwege een contract. Het is één getal dat meer slechte verzendingen heeft tegengehouden dan welke waarschuwingsbanner dan ook.

Waarom dit strenger is dan nodig voor jou: het gaat eigenlijk niet om jou. De reputatie van bulkverzending is een gedeelde bron, en één slordige lijst vergiftigt de put voor iedereen die vanaf dezelfde infrastructuur verstuurt. Klacht- en bouncepercentages per tenant worden gemonitord, en een account waarvan de percentages de drempel overschrijden wordt hier afgeremd — voordat een provider het bij iedereen tegelijk doet.

Achter elke rij in de lijst heeft iemand ja gezegd.

Vier wegen naar binnen

Elke route naar je lijst ben jij, handelend over je eigen data

Er is geen service-token-invoerkanaal en geen zusterproduct dat stilletjes in je contacten schrijft. Wil je iemand op een lijst, dan heeft één van deze vier die persoon daar gezet.

CSV-import

Kolom voor kolom gemapt, genormaliseerd bij het wegschrijven, MX-gecontroleerd zodat dode en verkeerd getypte domeinen worden gepakt voordat ze hard bouncen, en binnenkomen met een basis die je expliciet instelt. De import krijgt een id, en elk contact dat het aanmaakt verwijst daarnaar terug.

Een ClickSomo-formulier

Gemaakt uit hetzelfde document als alles anders, met validatie, een honeypot en een snelheidslimiet. Een inzending is de enige route die op legitieme wijze consent kan opleveren, want het is de enige waarbij de persoon zelf aanwezig is.

Een pagina die je in dash-b hebt gebouwd

De dashboarddesigner publiceert pagina's; een formulier erop post hierheen met je eigen credentials. Dezelfde validatie, dezelfde consent-afhandeling, geen tweede integratie om te onderhouden.

De publieke API

POST /v1/contacts met je eigen token, upsert-semantiek, idempotency-sleutel wordt gerespecteerd. Je app weet al wie zich heeft aangemeld; dit is het kortste pad van dat feit naar een funnel.

Segmenten zijn een predicaat, gecompileerd

Een segment is een opgeslagen predicaatboom over contactvelden, attributen, tags, lijstlidmaatschap en gedrag, gecompileerd naar SQL en gecachet met een telling. De operatoren zijn de gewone — equals, not equals, in, not in, starts with, ends with, contains, is set, is not set — gecombineerd met and, or en not tot welke diepte je maar nodig hebt.

Bekijk het eerst voordat je het gebruikt. Het endpoint geeft echte contacten terug, dus de vraag "wie zit hier nu eigenlijk in" beantwoord je door te kijken in plaats van te versturen en erachter te komen.

Segmenten doen daarna dubbel werk: als publiek voor een campagne, als voorwaarde op een funnel-tak, en als trigger op zichzelf — segment_enter start een run zodra iemand in aanmerking komt.

Stille regelmatigenSegmentvoorbeeld · 412
  • 1Tagtags contains "regular"
  • 2Attribuutattrs.total_orders >= 3 — jouw veld, jouw naam ervoor.
  • 3GedragGeen order.paid-event in de afgelopen 90 dagen.
  • 4ToestemmingEen bruikbare e-mailbasis. Contacten zonder e-mailadres tellen niet mee, omdat ze toch niet gemaild konden worden.
  • iVoorbeeld412 contacten, opgesomd. Opnieuw geteld bij verzending, want een segment is een vraag en geen momentopname.

Gecompileerd naar SQLAantal gecachet, antwoord live

Suppressie, en wanneer die wordt gecontroleerd

Suppressies zijn projectgebonden en globaal: hard bounces, klachten, uitschrijvingen, handmatige invoer en roladressen. Ze worden gecontroleerd op verzendmoment, en daarna nog eens binnen de verzendservice zelf.

Dat tweede woord doet het werk. Een funnel met een wachttijd van drie dagen heeft een venster van drie dagen waarin iemand zich kan uitschrijven, en een systeem dat suppressie controleerde toen het bericht in de wachtrij kwam, mailt hem toch nog. Controleren op verzendmoment is het verschil tussen een uitschrijving respecteren en er alleen een registreren.

Wissen werkt hetzelfde: een verwijderverzoek verwijdert het contact en de berichtgeschiedenis hier, en bereikt elke zusterservice die een kopie had via hetzelfde interne kanaal dat de rest van de familie gebruikt. Er is één plek om te vragen en één ding dat gebeurt.