{
  "version": "1.0",
  "schema": "https://entitymap.org/spec/v1.0",
  "profile": "core",
  "publisher": {
    "name": "Niko Karppinen",
    "url": "https://karppinen.one"
  },
  "generated": "2026-10-04T00:00:00Z",
  "verificationStatus": "generator-draft",
  "entities": [
    {
      "entityId": "e_002",
      "@type": "Person",
      "name": "Niko Karppinen",
      "description": "SEO and web analytics consultant working since 2017 across ecommerce, telecoms, public sector, consumer and B2B. He turns messy tracking and reporting into systems teams can measure and explain.",
      "audienceType": "general",
      "hasChunks": [
        {
          "chunkId": "c_001",
          "text": "I like untangling messy tracking setups, bringing scattered reports together and making site structures clearer. I want people to understand what is happening and decide what to do next.",
          "sourceUrl": "https://karppinen.one/about/",
          "pageTitle": "About Niko Karppinen",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "definition"
        },
        {
          "chunkId": "c_003",
          "text": "I have worked with SEO, analytics, and digital marketing since 2017. In that time, I have worked with organisations in ecommerce, telecommunications, insurance, healthcare, the public sector, B2B, and consumer services.",
          "sourceUrl": "https://karppinen.one/about/",
          "pageTitle": "About Niko Karppinen",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "evidence"
        },
        {
          "chunkId": "c_004",
          "text": "AI can help apply a clear process more consistently. It does not fix bad source data, unclear ownership, or a process that nobody really understands.",
          "sourceUrl": "https://karppinen.one/about/",
          "pageTitle": "About Niko Karppinen",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "example"
        }
      ]
    },
    {
      "entityId": "e_012",
      "@type": "karppinen:Guide",
      "name": "Cookiebot guide",
      "description": "A simplified walkthrough for installing Cookiebot and wiring Consent Mode defaults, including where to place the code.",
      "audienceType": "technical",
      "hasChunks": [
        {
          "chunkId": "c_017",
          "text": "This guide takes a direct Cookiebot website implementation from adding the scripts to browser validation. Site owners can use the implementation notes, marketing and analytics specialists can use the expected consent states, and developers can copy and adapt the generated code.",
          "sourceUrl": "https://karppinen.one/templates/cookiebot-guide/",
          "pageTitle": "Cookiebot guide",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "procedure"
        },
        {
          "chunkId": "c_018",
          "text": "Basic and Advanced Consent Mode describe when a tag loads, not which default snippet you copy. With Basic Consent Mode, the tag stays blocked until the relevant consent is granted. With Advanced Consent Mode, the tag loads with denied defaults and sends limited cookieless measurements.",
          "sourceUrl": "https://karppinen.one/templates/cookiebot-guide/",
          "pageTitle": "Cookiebot guide",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "procedure"
        }
      ],
      "relations": [
        { "predicate": "AUTHORED_BY", "targetId": "e_002", "targetName": "Niko Karppinen" }
      ]
    },
    {
      "entityId": "e_015",
      "@type": "Methodology",
      "name": "Content consumption measurement",
      "description": "An article-level measurement model that combines progress through the article body with qualifying reading time to estimate whether content was read.",
      "audienceType": "technical",
      "hasChunks": [
        {
          "chunkId": "c_022",
          "text": "That requires an article-specific measurement layer. This article uses progress through the article body and qualifying time to build a more transparent estimate of content consumption.",
          "sourceUrl": "https://karppinen.one/blog/content-consumption-metrics/",
          "pageTitle": "Are people reading your articles? A practical guide to content consumption metrics",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "definition"
        },
        {
          "chunkId": "c_023",
          "text": "An Estimated Article Read is still an estimate based on observable behaviour. It does not prove that someone read every word, paid attention throughout the visit or understood the content.",
          "sourceUrl": "https://karppinen.one/blog/content-consumption-metrics/",
          "pageTitle": "Are people reading your articles? A practical guide to content consumption metrics",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "evidence"
        }
      ],
      "relations": [
        { "predicate": "AUTHORED_BY", "targetId": "e_002", "targetName": "Niko Karppinen" }
      ]
    },
    {
      "entityId": "e_016",
      "@type": "Methodology",
      "name": "Page classification for analytics",
      "description": "Giving every page a page type and a primary topic so reports can compare understandable groups of pages instead of thousands of URLs (Finnish article).",
      "audienceType": "general",
      "hasChunks": [
        {
          "chunkId": "c_024",
          "text": "Kokonaisuutta voidaan selkeyttää antamalla jokaiselle sivulle kaksi perustietoa: millainen sivu se on ja mihin pääaiheeseen se kuuluu. Näin raportissa voidaan tarkastella ymmärrettäviä ryhmiä ja verrata yksittäistä sivua muihin samankaltaisiin sivuihin.",
          "sourceUrl": "https://karppinen.one/fi/blog/sivujen-luokittelu-analytiikassa/",
          "pageTitle": "Mitä verkkosivustosi luvut kertovat? Sivujen luokittelu auttaa ymmärtämään kokonaisuutta",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "definition"
        }
      ],
      "relations": [
        { "predicate": "AUTHORED_BY", "targetId": "e_002", "targetName": "Niko Karppinen" }
      ]
    },
    {
      "entityId": "e_017",
      "@type": "karppinen:Guide",
      "name": "HubSpot form tracking in GTM",
      "description": "A GTM template and lookup backend that push successful HubSpot form submissions to the dataLayer with the real form name, keeping the HubSpot token server-side.",
      "audienceType": "technical",
      "hasChunks": [
        {
          "chunkId": "c_025",
          "text": "This template does neither. HubSpot stays the source of truth for the form name, a small backend service looks the name up with a server-side credential, and GTM receives an analytics-friendly event.",
          "sourceUrl": "https://karppinen.one/templates/hubspot-form-tracking-gtm/",
          "pageTitle": "Track HubSpot form submissions in GTM with the real form name",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "definition"
        },
        {
          "chunkId": "c_026",
          "text": "The form name is not secret, but the HubSpot token is. Never call the HubSpot API directly from the browser and never paste the token into a GTM variable or template field.",
          "sourceUrl": "https://karppinen.one/templates/hubspot-form-tracking-gtm/",
          "pageTitle": "Track HubSpot form submissions in GTM with the real form name",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "procedure"
        }
      ],
      "relations": [
        { "predicate": "AUTHORED_BY", "targetId": "e_002", "targetName": "Niko Karppinen" },
        { "predicate": "RELATES_TO", "targetId": "e_018", "targetName": "Form taxonomy" }
      ]
    },
    {
      "entityId": "e_018",
      "@type": "Taxonomy",
      "name": "Form taxonomy",
      "description": "A controlled list of form categories and types that gives every tracked form one consistent value, whoever builds it.",
      "audienceType": "general",
      "hasChunks": [
        {
          "chunkId": "c_027",
          "text": "Name a form yourself and reporting depends on whoever named it. Contact, Get in Touch and Contact Form EN become three rows instead of one. A form type fixes that above the name.",
          "sourceUrl": "https://karppinen.one/tools/form-name-builder/",
          "pageTitle": "Form name builder",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "definition"
        },
        {
          "chunkId": "c_028",
          "text": "Answer two questions about your form, give it a name, and you get one consistent value to track it with — the same value every time, whoever builds the next form.",
          "sourceUrl": "https://karppinen.one/tools/form-name-builder/",
          "pageTitle": "Form name builder",
          "publisher": "Niko Karppinen",
          "retrieved": "2026-10-04T00:00:00Z",
          "contentType": "procedure"
        }
      ],
      "relations": [
        { "predicate": "AUTHORED_BY", "targetId": "e_002", "targetName": "Niko Karppinen" }
      ]
    }
  ]
}
