Adobe Analytics implementations accumulate hundreds of dimensions, metrics, segments, calculated metrics, and Workspace projects — with no built-in way to see how they relate to each other.
The knowledgegraph module builds an RDF Knowledge Graph out of your Adobe Analytics implementation, connecting every component (dimensions, metrics, marketing channels, segments, calculated metrics, date ranges) to the report suites they belong to, and — when Workspace projects are loaded — to each other, through actual usage.
It relies on the WorkspaceManager class to parse Workspace project definitions, and on rdflib to build, serialize, and query the resulting graph with SPARQL.
Not loaded by default: unlike most of the package,
KnowledgeGraphis not re-exported from the top-levelaanalytics2package (noimport aanalytics2; aanalytics2.KnowledgeGraph(...)). Import it explicitly from its module:from aanalytics2.knowledgegraph import KnowledgeGraph
Building the graph creates RDF entities (as URIRef nodes) for:
- ReportSuite — one per rsid considered.
- Dimension / Metric — scoped per report suite (the same dimension ID on two report suites becomes two distinct nodes).
- MarketingChannel — the marketing channel rules configured for a report suite.
- Segment / CalculatedMetric / DateRange — company-wide (not scoped to a single report suite).
- Workspace — one per project loaded via
loadProjects.
On top of these entities, buildGraph derives two kinds of relationships that aren't available anywhere else in the API:
- Usage counts : how many times each dimension, metric, segment, calculated metric, and report suite is referenced across segments, calculated metrics, and loaded Workspace projects (
segmentUsage,metricUsage,projectUsage). - Co-occurrence : which dimensions are used together with which metrics, and which dimensions are used together with which segments, inside the same Workspace visualization — with a count of how often that pairing occurs.
The result is a rdflib.Graph that can be serialized to Turtle (.ttl) and queried with SPARQL, or explored with any RDF-compatible tool. The full node/predicate vocabulary is described in Ontology.
from aanalytics2.knowledgegraph import KnowledgeGraphKnowledgeGraph connects to Adobe Analytics on instantiation — it needs a config object the same way Analytics or Login do.
import aanalytics2 as api2
from aanalytics2.knowledgegraph import KnowledgeGraph
cfg = api2.importConfigFile('config_analytics.json', return_object=True)
# Auto-detect the most commonly used report suite from your projects
kg = KnowledgeGraph(config=cfg)
# Build the graph across every report suite in the company
kg_all = KnowledgeGraph(config=cfg, rsids="all")
# Restrict to specific report suites
kg_some = KnowledgeGraph(config=cfg, rsids=["rsid_a", "rsid_b"])Arguments:
- config : OPTIONAL : The config dictionary/
ConfigObjreturned byimportConfigFile(..., return_object=True)(orconfigure(..., return_object=True)). - companyId : OPTIONAL : The company ID to use for building the knowledge graph. If not provided, the first company ID returned by
Login.getCompanyId()is used. - rsids : OPTIONAL : Which report suite(s) to include (
list[str],str, or"all").- Not provided (default) : the report suite ID most frequently used across your Workspace projects is auto-detected and used.
"all": every (non-virtual) report suite in the company is used.str: a single report suite ID.list: an explicit list of report suite IDs.
- filterDims : OPTIONAL : If set to
True(default), entry/exit dimensions (/entry,/exit) are excluded and only Oberon-reportable dimensions are kept.
Instantiating the class performs several API calls right away, before you call any method:
- Connects via
Loginand resolves thecompanyId. - Retrieves the report suites (
getReportSuites(extended_info=True)). - Resolves
rsids(auto-detecting from your most-used project's report suite when not provided). - Fetches dimensions, metrics, and marketing channels per report suite concurrently (
ThreadPoolExecutor, up to 10 workers). - Fetches segments, calculated metrics, date ranges, project stubs, and annotations for the whole company.
- Builds one
rdflib.Namespaceper entity type (plus one dimension/metric namespace per report suite), stored inkg.namespaces. See Namespaces.
Once instantiated, the KnowledgeGraph object exposes the following attributes:
kg.companyId: the resolved company ID.kg.rsids: the list of report suite IDs considered.kg.reportSuites:DataFrameof report suite metadata.kg.dimensions/kg.metrics:dictkeyed by rsid, each value a raw list of dimension/metric dicts.kg.marketingChannels:dictkeyed by rsid.kg.segments/kg.calculatedMetrics/kg.dateRanges: raw lists (extended info), company-wide.kg.projects: raw list of project stubs (id,name,rsid,modified, …) — not full definitions. UseloadProjectsto fetch full definitions.kg.annotations: raw list of annotations.kg.namespaces:dictofrdflib.Namespaceobjects, one per entity type ("segments","metrics","reportSuites","usage", …), plus one"{rsid}/dimensions"/"{rsid}/metrics"pair per report suite. See Namespaces.kg.project_details: populated byloadProjects— list ofWorkspaceManagerinstances, one per loaded project.kg.graph: populated bybuildGraph— the resultingrdflib.Graph.
Fetch full Workspace project definitions and parse them (via WorkspaceManager) so buildGraph can extract dimension/metric/segment/calculated-metric usage and co-occurrence from them.
This step is optional — without it, buildGraph still produces the full component graph and usage counts from segments and calculated metrics, but no project-derived usage or co-occurrence.
# Load the 20 most recently modified projects
kg.loadProjects(20)
# Load a random sample of 20 projects instead
kg.loadProjects(20, sampleMethod='random')
# Load specific projects by ID
kg.loadProjects(['5f9...abc', '5f9...def'])
# Load every project in the company (can take a long time)
kg.loadProjects('all')Arguments:
- projects : REQUIRED : Which projects to load.
int: number of projects to load, selected viasampleMethod.list: explicit list of project IDs."all": every project in the company. This fetches each project definition individually and can take a large amount of time on big accounts.
- sampleMethod : OPTIONAL : Used only when
projectsis anint. (str : default'most_recent')'most_recent': the most recently modified projects.'random': a random sample of projects.
Project definitions are fetched concurrently (ThreadPoolExecutor, up to 6 workers) and stored as WorkspaceManager instances in kg.project_details.
Build the RDF graph from everything fetched at instantiation (and from kg.project_details, if loadProjects was called beforehand).
graph = kg.buildGraph()
# Build and save straight to a Turtle file
graph = kg.buildGraph(save=True, filename='my_graph.ttl')
# Print progress while building
graph = kg.buildGraph(verbose=True)Arguments:
- save : OPTIONAL : If set to
True, serializes the graph to a Turtle file. (bool : defaultFalse) - filename : OPTIONAL : Filename used when
save=True. A.ttlextension is appended automatically if missing. (str : default'knowledge_graph.ttl') - verbose : OPTIONAL : If set to
True, prints progress statements while the graph is being built.
Returns the built rdflib.Graph, also stored on kg.graph.
What gets added to the graph:
- One node per ReportSuite, Dimension, Metric, MarketingChannel, Segment, CalculatedMetric, and DateRange, each carrying its own properties (
RDFS.label,id,type,reportable,segmentable, tags, share counts, last-access timestamps, …) under its entity namespace (kg.namespaces[...]). - Classification dimensions (IDs containing
.) are linked to their parent viaparent_dimension/children_dimensionpredicates. - Every
SegmentandCalculatedMetricis scanned (scanSegment/scanCalculatedMetric) to incrementusage.segmentUsage/usage.metricUsageon every dimension/metric/report suite it references. - One Workspace node per project in
kg.project_details(populated byloadProjects), linked to its report suite, with each panel's text, freeform table, and visualization content attached, and every dimension/metric/calculated-metric/segment it uses incrementingusage.projectUsage. - Co-occurrence blank nodes: a
MetricCooccurrencenode for every (dimension, metric) pair found together in the same Workspace visualization, and aSegmentCooccurrencenode for every (dimension, segment) pair — each carrying acooccurrenceCountand thersidit was observed on. The dimension and metric/segment nodes are additionally linked directly viausedWithMetric/usedWithDimensionandusedWithSegment/usedWithDimensionpredicates.
The full list of node types and predicates produced here is detailed in Ontology.
Serialize the already-built graph (kg.graph) to a Turtle file. Use this when you want to save the graph separately from buildGraph, e.g. after running additional edits on kg.graph.
kg.exportGraph(filename='my_graph.ttl')Arguments:
- filename : REQUIRED : The name of the Turtle file to write. A
.ttlextension is appended automatically if missing.
Run a SPARQL query against the graph built by buildGraph().
Unlike calling kg.graph.query(...) directly, this returns a list of plain Python dictionaries (one per result row, values converted with .toPython()) instead of raw rdflib Result rows — easier to load straight into a pandas.DataFrame.
rows = kg.query("""
PREFIX usage: <http://analytics.com/COMPANYID/usage#>
SELECT ?dimension ?count WHERE {
?dimension usage:projectUsage ?count .
}
ORDER BY DESC(?count)
LIMIT 10
""")
import pandas as pd
df = pd.DataFrame(rows)Arguments:
- sparql_string : REQUIRED : The SPARQL query to execute.
Returns a list of dict, one per result row, keyed by SPARQL variable name.
import aanalytics2 as api2
from aanalytics2.knowledgegraph import KnowledgeGraph
# 1. Authenticate
cfg = api2.importConfigFile('config_analytics.json', return_object=True)
# 2. Build the component graph across every report suite
kg = KnowledgeGraph(config=cfg, rsids="all")
# 3. Load the 50 most recently modified projects to enrich the graph
# with real usage and co-occurrence data
kg.loadProjects(50, sampleMethod='most_recent')
# 4. Build and save the graph
graph = kg.buildGraph(save=True, filename='analytics_knowledge_graph.ttl', verbose=True)
# 5. Query it — e.g. the 10 most-used dimensions across loaded projects
rows = kg.query(f"""
PREFIX usage: <http://analytics.com/{kg.companyId}/usage#>
SELECT ?dimension ?count WHERE {{
?dimension usage:projectUsage ?count .
}}
ORDER BY DESC(?count)
LIMIT 10
""")
for row in rows:
print(row['dimension'], row['count'])
# 6. Re-export the graph later without rebuilding it
kg.exportGraph(filename='analytics_knowledge_graph_backup.ttl')This section is also shipped as a standalone file,
aanalytics2/resources/kg_ontology.md, which the MCP server serves to LLM clients as theontology://knowledge-graphresource. Keep the two in sync when the schema changes.
For a company with ID {companyId}, the following namespaces are minted at instantiation and stored in kg.namespaces:
Key in kg.namespaces |
URI pattern | Used for |
|---|---|---|
reportSuites |
http://analytics.com/{companyId}/reportSuite# |
ReportSuite nodes (reportSuites[rsid]) and the rs:* predicates |
dimensions |
http://analytics.com/{companyId}/dimension# |
the dim:* predicates attached to Dimension nodes |
metrics |
http://analytics.com/{companyId}/metric# |
the met:* predicates attached to Metric nodes |
marketingChannels |
http://analytics.com/{companyId}/marketingChannel# |
the mc:* predicates attached to MarketingChannel nodes |
segments |
http://analytics.com/{companyId}/segment# |
the seg:* predicates attached to Segment nodes |
calculatedMetrics |
http://analytics.com/{companyId}/calculatedMetric# |
the cm:* predicates attached to CalculatedMetric nodes |
dateRange |
http://analytics.com/{companyId}/dateRange# |
the dr:* predicates attached to DateRange nodes |
projects |
http://analytics.com/{companyId}/projects# |
the proj:* predicates, and the URI of the single "projects root" node |
usage |
http://analytics.com/{companyId}/usage# |
the usage:* predicates (usage counts, co-occurrence) |
{rsid}/dimensions, {rsid}/metrics |
http://analytics.com/{companyId}/{rsid}/dimension# / .../{rsid}/metric# |
one pair per report suite, bound as serialization prefixes — the actual Dimension/Metric node URIs use the pattern below, not these namespace objects |
Entity nodes (other than ReportSuite) are not minted from the namespace objects above — each has its own dedicated URI template:
| Entity | Node URI pattern |
|---|---|
| ReportSuite | http://analytics.com/{companyId}/reportSuite#{rsid} |
| Dimension | http://analytics.com/{companyId}/{rsid}/dimension/{dimensionId} |
| Metric | http://analytics.com/{companyId}/{rsid}/metric/{metricId} |
| MarketingChannel container (one per rsid) | http://analytics.com/{companyId}/{rsid}/marketingChannel/ |
| MarketingChannel (each configured channel) | http://analytics.com/{companyId}/{rsid}/marketingChannel/{channelId} |
| Segment | http://analytics.com/{companyId}/segment/{segmentId} |
| CalculatedMetric | http://analytics.com/{companyId}/calculatedMetric/{calculatedMetricId} |
| DateRange | http://analytics.com/{companyId}/dateRange/{dateRangeId} |
| Workspace (project) | http://analytics.com/{companyId}/projects/{projectId} |
| Projects root | http://analytics.com/{companyId}/projects# (the projects namespace itself, used as a single node every Workspace is attached to via proj:contains) |
| MetricCooccurrence / SegmentCooccurrence | blank node (BNode()) — no stable URI; found via the usage:dimension + usage:metric/usage:segment predicates |
Nodes are typed with rdf:type (RDF.type) using the following (literal) values:
| rdf:type | Meaning |
|---|---|
ReportSuite |
a report suite |
Dimension |
a dimension, scoped to one report suite |
Metric |
a metric, scoped to one report suite |
MarketingChannels |
the marketing channel container for a report suite |
MarketingChannel |
one configured marketing channel rule |
Segment |
a segment (company-wide) |
CalculatedMetric |
a calculated metric (company-wide) |
DateRange |
a date range (company-wide) |
Workspace |
a Workspace project — only present after loadProjects + buildGraph |
MetricCooccurrence |
blank node recording that a dimension and a metric were used together in a Workspace visualization, with a cooccurrenceCount |
SegmentCooccurrence |
blank node recording that a dimension and a segment were used together in a Workspace visualization, with a cooccurrenceCount |
The tables below use short prefixes for readability. They map to kg.namespaces as follows:
dim → kg.namespaces['dimensions']
met → kg.namespaces['metrics']
mc → kg.namespaces['marketingChannels']
seg → kg.namespaces['segments']
cm → kg.namespaces['calculatedMetrics']
rs → kg.namespaces['reportSuites']
dr → kg.namespaces['dateRange']
proj → kg.namespaces['projects']
usage → kg.namespaces['usage']
| Predicate | Usage |
|---|---|
rdf:type |
node type, see Node types |
rdfs:label |
human-readable name of a node |
rdfs:comment |
description of a node, when the source component has one |
dim:id / met:id / seg:id / cm:id / mc:id / dr:id / rs:id |
the raw Adobe Analytics component ID |
dim:dataType |
dimension data type (string, int, …) |
dim:classification |
true / false — whether the dimension ID contains a . (classification / sub-classification) |
dim:parent_dimension / dim:children_dimension |
links a classification dimension to its parent, and back |
dim:reportable / met:reportable / cm:reportable |
one triple per supported report type / product |
dim:segmentable / met:segmentable |
boolean |
dim:rsid / met:rsid / mc:rsid / seg:rsid / cm:rsid |
link from the component to its owning ReportSuite node |
met:type / cm:type |
metric / calculated metric type |
met:polarity / cm:polarity |
positive / negative |
mc:defines |
the marketing channel container → each configured channel |
mc:position / mc:override / mc:enabled |
channel rule configuration |
rs:currency |
ReportSuite currency |
rs:dimensions / rs:metrics / rs:marketingChannels / rs:segments / rs:calculatedMetrics |
ReportSuite → each of its component nodes |
seg:definition / cm:definition |
segment / calculated metric definition (JSON, as a string literal) |
seg:lastAccess / cm:lastAccess |
last recorded access, xsd:dateTime |
seg:tag / cm:tag |
one triple per tag name |
seg:shares / cm:shares |
number of shares |
dr:description / dr:definition |
date range metadata |
proj:contains |
the projects root node → each loaded Workspace |
proj:rsid |
Workspace → its ReportSuite |
proj:description / proj:created |
Workspace metadata |
proj:text |
text panel content (title, and body when not empty) |
proj:visualition (sic — kept as-is to match the current implementation) |
name of a Visualization panel |
proj:panelFreeForm |
name (and description) of a FreeForm panel |
proj:dimension_ref / proj:metric_ref / proj:calculated_ref |
back-links from a Dimension / Metric / CalculatedMetric node to every Workspace that uses it |
usage:segmentUsage / usage:projectUsage / usage:metricUsage |
integer counters on Dimension/Metric/ReportSuite/Segment/CalculatedMetric nodes: how many times it is referenced by segments, Workspace projects, or calculated metrics respectively |
usage:usedWithMetric / usage:usedWithDimension |
direct co-occurrence edge between a Dimension and a Metric node (both directions) |
usage:usedWithSegment / usage:usedWithDimension |
direct co-occurrence edge between a Dimension and a Segment node (both directions) |
usage:dimension / usage:metric / usage:segment |
from a MetricCooccurrence / SegmentCooccurrence blank node to the Dimension/Metric/Segment it relates |
usage:cooccurrenceCount |
how many times that specific pairing was observed |
usage:rsid |
from a cooccurrence blank node to the ReportSuite it was observed on |
Below is a Mermaid diagram of the main artefacts and relationships in the knowledge graph. It is not exhaustive, but it gives a good overview of the graph structure.
graph TD
ReportSuite -->|rs:dimensions| Dimension
ReportSuite -->|rs:metrics| Metric
ReportSuite -->|rs:marketingChannels| MarketingChannel
ReportSuite -->|rs:segments| Segment
ReportSuite -->|rs:calculatedMetrics| CalculatedMetric
Dimension -->|dim:parent_dimension| Dimension
Dimension -->|dim:children_dimension| Dimension
Segment -->|seg:rsid| ReportSuite
CalculatedMetric -->|cm:rsid| ReportSuite
MarketingChannel -->|mc:rsid| ReportSuite
ProjectsRoot["Projects (root)"] -->|proj:contains| Workspace
Workspace -->|proj:rsid| ReportSuite
Dimension -->|proj:dimension_ref| Workspace
Metric -->|proj:metric_ref| Workspace
CalculatedMetric -->|proj:calculated_ref| Workspace
Segment -.->|counted via usage:projectUsage| Workspace
Dimension -->|usage:usedWithMetric| Metric
Metric -->|usage:usedWithDimension| Dimension
Dimension -->|usage:usedWithSegment| Segment
Segment -->|usage:usedWithDimension| Dimension
MetricCooccurrence["MetricCooccurrence (blank node)"] -->|usage:dimension| Dimension
MetricCooccurrence -->|usage:metric| Metric
MetricCooccurrence -->|usage:cooccurrenceCount| Count
SegmentCooccurrence["SegmentCooccurrence (blank node)"] -->|usage:dimension| Dimension
SegmentCooccurrence -->|usage:segment| Segment
SegmentCooccurrence -->|usage:cooccurrenceCount| Count
ReportSuite -->|usage:segmentUsage / projectUsage / metricUsage| UsageCounters["usage counters"]
Dimension -->|usage:segmentUsage / projectUsage| UsageCounters
Metric -->|usage:metricUsage / projectUsage| UsageCounters