diff --git a/.diagram-design b/.diagram-design new file mode 100644 index 00000000..e155c7e6 --- /dev/null +++ b/.diagram-design @@ -0,0 +1 @@ +profile: absmartly diff --git a/docs/web-console-docs/warehouse-native/modes.mdx b/docs/web-console-docs/warehouse-native/modes.mdx index b29a0246..87e27ed8 100644 --- a/docs/web-console-docs/warehouse-native/modes.mdx +++ b/docs/web-console-docs/warehouse-native/modes.mdx @@ -33,49 +33,9 @@ In Hybrid mode, you keep the ABsmartly-managed data source as your default and a - When a goal is sourced from an external warehouse, ABsmartly makes the default source's exposures available to that warehouse so the two can be evaluated together. You enable this by pointing ABsmartly at an object store through the **[Exposures import](./get-started#step-4-configure-exposures-import-hybrid-only)** section on each external data source. - Because that import lands the exposures inside your warehouse, **goals sourced from your warehouse can filter and enrich those exposures** the same way Fully mode does — strip out bots and internal traffic, or join in your own attributes table. **Goals that stay managed by ABsmartly don't get this**, since their exposures never leave ABsmartly's default data source. -```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Manrope, system-ui, sans-serif", "primaryColor": "#ffffff", "primaryBorderColor": "#CA3721", "primaryTextColor": "#28293d", "lineColor": "#9296a6", "tertiaryColor": "#ffffff", "fontSize": "15px"}}}%% -flowchart TB - SDK(["Your app - ABsmartly SDK"]) - - subgraph ABC["ABsmartly (default)"] - DEFAULT[("Exposures (no filtering)
and managed goals")] - end - - subgraph EWH["Your warehouse (external)"] - IMPORT[("Imported
exposures")] - WGOALS[("Your goals")] - ATTR[("Your attributes")] - FILTER("Filter and enrich") - QUERY("Query interface") - end - - subgraph CLOUD["ABsmartly Cloud"] - ENGINE("Assignment logic, stats and
metric governance") - end - - SDK --> DEFAULT - DEFAULT -.->|"exposures import"| IMPORT - IMPORT --> FILTER - ATTR --> FILTER - FILTER --> QUERY - WGOALS --> QUERY - DEFAULT --> ENGINE - ENGINE -.->|"scheduled query"| QUERY - QUERY -.->|"aggregate results only"| ENGINE - - style ABC fill:#FBEDEA,stroke:#CA3721,stroke-width:1.5px,color:#28293d - style EWH fill:#EEF1FF,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style CLOUD fill:#FBEDEA,stroke:#CA3721,stroke-width:1.5px,color:#28293d - style DEFAULT fill:#ffffff,stroke:#CA3721,stroke-width:1.5px,color:#28293d - style IMPORT fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style WGOALS fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style ATTR fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style FILTER fill:#465BFF,stroke:#465BFF,stroke-width:1.5px,color:#ffffff - style QUERY fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style ENGINE fill:#ffffff,stroke:#CA3721,stroke-width:1.5px,color:#28293d - style SDK fill:#ffffff,stroke:#9296a6,stroke-width:1.5px,color:#28293d -``` +![Hybrid Warehouse Native architecture: the ABsmartly SDK sends exposures into ABsmartly's default source, which handles unfiltered managed goals directly and also imports exposures into the customer's external warehouse, where imported exposures, goals, and attributes are filtered and enriched before ABsmartly Cloud runs a scheduled query and returns only aggregate results. ABsmartly Cloud retains user-level data for exposures and any goals kept on the managed default source.](/img/warehouse-native/hybrid-architecture.svg) + +*Across the privacy boundary between your warehouse and ABsmartly Cloud, ABsmartly runs a scheduled query in and only aggregate results come back out — no user-level data crosses that boundary. The default source's exposures flow into your warehouse on a scheduled exposures import.* Hybrid lets you bring metrics into your warehouse at your own pace: you keep ABsmartly's battle-tested assignment and exposure pipeline, and move as many (or as few) of your goals into your warehouse as you like — gaining filtering and enrichment for each one you move. @@ -88,41 +48,9 @@ Because every exposure already lives in your warehouse, Fully extends Hybrid's w - **Filter exposures yourself.** You control the exposures table, so you can strip out bots, scrapers, internal traffic, or any other unwanted exposures before ABsmartly analyzes them — using your own logic in your own warehouse. - **Enrich exposures with your own attributes.** You can join in an external **attributes** table to add segmentation dimensions, then slice experiment results by those attributes. -```mermaid -%%{init: {"theme": "base", "themeVariables": {"fontFamily": "Manrope, system-ui, sans-serif", "primaryColor": "#ffffff", "primaryBorderColor": "#CA3721", "primaryTextColor": "#28293d", "lineColor": "#9296a6", "tertiaryColor": "#ffffff", "fontSize": "15px"}}}%% -flowchart TB - SDK(["Your app - ABsmartly SDK"]) - - subgraph WH["Your warehouse (default)"] - EXP[("Exposures")] - GOALS[("Goals")] - ATTR[("Your attributes")] - FILTER("Filter and enrich") - QUERY("Query interface") - end - - subgraph ABC["ABsmartly Cloud"] - ENGINE("Assignment logic, stats and
metric governance
no user-level data stored") - end - - SDK --> EXP - EXP --> FILTER - ATTR --> FILTER - FILTER --> QUERY - GOALS --> QUERY - ENGINE -.->|"scheduled query"| QUERY - QUERY -.->|"aggregate results only"| ENGINE - - style WH fill:#EEF1FF,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style ABC fill:#FBEDEA,stroke:#CA3721,stroke-width:1.5px,color:#28293d - style EXP fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style GOALS fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style ATTR fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style FILTER fill:#465BFF,stroke:#465BFF,stroke-width:1.5px,color:#ffffff - style QUERY fill:#ffffff,stroke:#465BFF,stroke-width:1.5px,color:#28293d - style ENGINE fill:#ffffff,stroke:#CA3721,stroke-width:1.5px,color:#28293d - style SDK fill:#ffffff,stroke:#9296a6,stroke-width:1.5px,color:#28293d -``` +![Fully Warehouse Native architecture: the ABsmartly SDK sends exposures into the customer's own warehouse, which is the default data source holding exposures, attributes, and goals, filtering and enriching every exposure before ABsmartly Cloud runs a scheduled query and returns only aggregate results, storing no user-level data.](/img/warehouse-native/fully-architecture.svg) + +*Across the privacy boundary between your warehouse and ABsmartly Cloud, ABsmartly runs a scheduled query in and only aggregate results come back out — no user-level data crosses that boundary.* :::info Why the exposure source matters Exposure-side filtering (bots, scrapers, internal traffic) and attribute enrichment both operate on the exposure stream, and only work once that stream lives inside your warehouse. In **Hybrid**, that's true for goals you source from your warehouse — their imported exposures can be filtered and enriched. It's **not** true for goals that stay managed by ABsmartly, since their exposures never leave the default data source. In **Fully**, every exposure lives in your warehouse, so filtering and enrichment apply to every goal. diff --git a/docusaurus.config.js b/docusaurus.config.js index 76193c50..508ec90f 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -56,8 +56,11 @@ const config = { locales: ["en"], }, - // Client modules for anchor redirects - clientModules: [require.resolve("./src/anchorRedirects.ts")], + // Client modules for anchor redirects and mermaid icon registration + clientModules: [ + require.resolve("./src/anchorRedirects.ts"), + require.resolve("./src/scripts/mermaidIcons.js"), + ], presets: [ [ diff --git a/package.json b/package.json index ca79f20b..2dba94df 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@docusaurus/plugin-ideal-image": "^3.10.2", "@docusaurus/preset-classic": "^3.10.2", "@docusaurus/theme-mermaid": "^3.10.2", + "@iconify-json/mdi": "^1.2.3", "@mdx-js/react": "^3.1.1", "clsx": "^2.1.0", "docusaurus-plugin-openapi-docs": "^5.1.3", diff --git a/src/scripts/mermaidIcons.js b/src/scripts/mermaidIcons.js new file mode 100644 index 00000000..eae66272 --- /dev/null +++ b/src/scripts/mermaidIcons.js @@ -0,0 +1,7 @@ +import { icons } from "@iconify-json/mdi"; + +if (typeof window !== "undefined") { + import("mermaid").then(({ default: mermaid }) => { + mermaid.registerIconPacks([{ name: icons.prefix, icons }]); + }); +} diff --git a/static/img/warehouse-native/fully-architecture.svg b/static/img/warehouse-native/fully-architecture.svg new file mode 100644 index 00000000..cf5ab6fb --- /dev/null +++ b/static/img/warehouse-native/fully-architecture.svg @@ -0,0 +1,128 @@ + + + Fully Warehouse Native architecture + Architecture diagram showing the customer's SDK sending exposures into their own warehouse, which is the default data source holding exposures, attributes, and goals, filtering and enriching every exposure before ABsmartly Cloud runs a scheduled query and returns only aggregate results, storing no user-level data. + + + + + + + + + + + + + + + + YOUR WAREHOUSE — DEFAULT + + + + + + + ABSMARTLY CLOUD + + + + + + + + + + + + + + QUERY + + + RESULT + + + + + + + + Your app + ABsmartly SDK + + + + + + + + Exposures + no server filter + + + + + + + + Your attributes + segmentation + + + + + + + + Goals + metrics table + + + + + + + + Filter & enrich + every exposure + + + + + + + + Query interface + scheduled reads + + + + + + + + Assignment stats + & governance + no user-level data + + + + LEGEND + + + Your warehouse + + + ABsmartly Cloud + + + Data flow + + + Scheduled query out + + + Aggregate results only + diff --git a/static/img/warehouse-native/hybrid-architecture.svg b/static/img/warehouse-native/hybrid-architecture.svg new file mode 100644 index 00000000..eb94655c --- /dev/null +++ b/static/img/warehouse-native/hybrid-architecture.svg @@ -0,0 +1,155 @@ + + + Hybrid Warehouse Native architecture + Architecture diagram showing the customer's SDK sending exposures into ABsmartly's default source, which handles unfiltered managed goals directly and also imports exposures into the customer's external warehouse, where imported exposures, goals, and attributes are filtered and enriched before ABsmartly Cloud runs a scheduled query and returns only aggregate results. ABsmartly Cloud retains user-level data for exposures and any goals kept on the managed default source. + + + + + + + + + + + + + + + + YOUR WAREHOUSE — EXTERNAL + + + + + + + ABSMARTLY CLOUD + + + + + + + + + + + + + + + + + + + + + + + + MANAGED + + + QUERY + + + RESULT + + + + + + + + Your app + ABsmartly SDK + + + + + + DEFAULT + + + + Exposures & managed goals + no filtering + + + + + + + + Imported exposures + via object store + + + + + + + + Your goals + warehouse-sourced + + + + + + + + Your attributes + segmentation + + + + + + + + Filter & enrich + warehouse goals only + + + + + + + + Query interface + scheduled reads + + + + + + + + Assignment stats + & governance + holds managed-source data + + + + LEGEND + + + Your warehouse + + + ABsmartly Cloud + + + Data flow + + + Managed, unfiltered + + + Scheduled query out + + + Aggregate results only + diff --git a/yarn.lock b/yarn.lock index bcdbbdea..8b419119 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2258,7 +2258,14 @@ resolved "https://registry.yarnpkg.com/@hookform/error-message/-/error-message-2.0.1.tgz#6a37419106e13664ad6a29c9dae699ae6cd276b8" integrity sha512-U410sAr92xgxT1idlu9WWOVjndxLdgPUHEB8Schr27C9eh7/xUnITWpCMF93s+lGiG++D4JnbSnrb5A21AdSNg== -"@iconify/types@^2.0.0": +"@iconify-json/mdi@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@iconify-json/mdi/-/mdi-1.2.3.tgz#5e4ee9d8c8aaad04381c8cc6c6edbe3327f031b5" + integrity sha512-O3cLwbDOK7NNDf2ihaQOH5F9JglnulNDFV7WprU2dSoZu3h3cWH//h74uQAB87brHmvFVxIOkuBX2sZSzYhScg== + dependencies: + "@iconify/types" "*" + +"@iconify/types@*", "@iconify/types@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==