From 7fc4082f8b6945724cdc426b7b9f26f084c4a917 Mon Sep 17 00:00:00 2001 From: Jonas Alves Date: Tue, 27 Jan 2026 19:03:09 +0000 Subject: [PATCH] feat: improve redirects with splat patterns and case-insensitive matching (#246) * feat: improve redirects with splat patterns and case-insensitive matching - Consolidate server redirects using Netlify splat patterns (~75 rules vs 169) - Make anchor redirects case-insensitive to avoid duplication - Add anchor redirects for pages with changed section headings - Remove case-only redirects that could cause infinite loops - Update test script with comprehensive redirect tests * fix: remove duplicate SDK-API directory from old location The files were incorrectly copied instead of renamed during a previous merge. Removing the old docs/SDK-API/ directory so redirects work properly. Files already exist in docs/APIs-and-SDKs/SDK-API/. * fix: add explicit base path redirects for splat patterns Splat patterns (/*) don't match bare paths without trailing slash. Added explicit redirects for: - /docs/SDK-Documentation and /docs/SDK-Documentation/Advanced - /docs/sdk-documentation and /docs/sdk-documentation/advanced - /docs/Examples and /docs/examples - /docs/API, /docs/sdk-api, /docs/SDK-API - /docs/web-console-api and /docs/Web-Console-API --- docs/SDK-API/absmartly-collector-api.info.mdx | 25 -- docs/SDK-API/collector-health-check.api.mdx | 44 --- docs/SDK-API/context-create.api.mdx | 66 ---- docs/SDK-API/context-get.api.mdx | 54 --- docs/SDK-API/context-publish-batch.api.mdx | 134 -------- docs/SDK-API/context-publish.api.mdx | 130 ------- docs/SDK-API/experiment-get.api.mdx | 50 --- docs/SDK-API/sidebar.js | 1 - src/anchorRedirects.ts | 88 ++++- static/_redirects | 154 +++++++-- test-all-urls.js | 318 ++++++++++++++++-- 11 files changed, 504 insertions(+), 560 deletions(-) delete mode 100644 docs/SDK-API/absmartly-collector-api.info.mdx delete mode 100644 docs/SDK-API/collector-health-check.api.mdx delete mode 100644 docs/SDK-API/context-create.api.mdx delete mode 100644 docs/SDK-API/context-get.api.mdx delete mode 100644 docs/SDK-API/context-publish-batch.api.mdx delete mode 100644 docs/SDK-API/context-publish.api.mdx delete mode 100644 docs/SDK-API/experiment-get.api.mdx delete mode 100644 docs/SDK-API/sidebar.js diff --git a/docs/SDK-API/absmartly-collector-api.info.mdx b/docs/SDK-API/absmartly-collector-api.info.mdx deleted file mode 100644 index 8fdcf195..00000000 --- a/docs/SDK-API/absmartly-collector-api.info.mdx +++ /dev/null @@ -1,25 +0,0 @@ ---- -id: absmartly-collector-api -title: "ABsmartly Collector API" -description: "An OpenAPI Specification that describes the ABsmartly Collector API. This API is mainly used when using ABsmartly in a language that does not yet have a supported SDK." -sidebar_label: Introduction -sidebar_position: 0 -hide_title: true -custom_edit_url: null ---- - -import ApiLogo from "@theme/ApiLogo"; -import SchemaTabs from "@theme/SchemaTabs"; -import TabItem from "@theme/TabItem"; -import Export from "@theme/ApiExplorer/Export"; - -Version: 1.0.0 - -

ABsmartly Collector API

- - - -An OpenAPI Specification that describes the ABsmartly Collector API. This API is mainly used when using ABsmartly in a language that does not yet have a supported SDK. - -

Authentication

Security Scheme Type:apiKey
Header parameter name:X-API-Key

Contact

API Support: api@absmartly.com

License

- \ No newline at end of file diff --git a/docs/SDK-API/collector-health-check.api.mdx b/docs/SDK-API/collector-health-check.api.mdx deleted file mode 100644 index 6601586b..00000000 --- a/docs/SDK-API/collector-health-check.api.mdx +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: collector-health-check -title: "Check Service Health" -description: "A GET request to check that the service is running as expected." -sidebar_label: "Check Service Health" -hide_title: true -hide_table_of_contents: true -api: eJytU02L2zAQ/SvDnL1OttCLT3W3yzbsoYGkUAg5TOTZSNSWFGmcxhj/9yLbIWlLe+rJ8ui9+Xjz1KPQMWKxQ+XqmpW4gPsMK44qGC/GWSywhJfnLQQ+tRwFxIHSrL6DaBIQzRA5nI1iMBFCa62xR6AIfPGshKscM3SeA6VsqwqLW6nPTLXop5QNMwwcvbORIxY9vlsu0+fXRjYczhxSHT0yOxwyfP9vpHVyQw8ZNizapS6OLJihJ9FY4OIKyTCO1KRJj22osUAt4mOxWESy1cFdcjrEhoLUXW7c4vyIwz6xVBuMdCOt9OaV03F/f7VRmptpuiugR+k8Y4E0BTK01KT/bw/levUwhUwaSDNVHEaVTq0JXGEhoeU0kbFvbkxlpE7c8uPcHjxdhYZyvcIM01yTPo/5Ml/iH4u28MWzLdcr2HhW5s2ocWvTqifsgeO49L9UyWGrTUynJH5DxtYdtJEr+KHZQhuTO25cY4GgJnts6chzGcfT1joW0HRmIIit9y4IV7D59JoMpZwVUpLGnhUbm55gmCE3ZOpJ1w+3dSnXJMfURrGNfEdeB+eDYaEwmcS7KA3ZO8RoUtjMTp+M+7t+/dgWW/kvb2Z2hvBFFr4mY1ProyH72bU7vLp2n6F2UVKo7w8U+WuohyGFTy2H0YkZnikYOiSL7Pb3D+HleYvD8BN8TGJM -sidebar_class_name: "get api-method" -info_path: docs/SDK-API/absmartly-collector-api -custom_edit_url: null ---- - -import ApiTabs from "@theme/ApiTabs"; -import DiscriminatorTabs from "@theme/DiscriminatorTabs"; -import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; -import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; -import MimeTabs from "@theme/MimeTabs"; -import ParamsItem from "@theme/ParamsItem"; -import ResponseSamples from "@theme/ResponseSamples"; -import SchemaItem from "@theme/SchemaItem"; -import SchemaTabs from "@theme/SchemaTabs"; -import Markdown from "@theme/Markdown"; -import OperationTabs from "@theme/OperationTabs"; -import TabItem from "@theme/TabItem"; - -

Check Service Health

- - - - - -A GET request to check that the service is running as expected. - -
- -Server is healthy - -
- -Server is not healthy - -
- \ No newline at end of file diff --git a/docs/SDK-API/context-create.api.mdx b/docs/SDK-API/context-create.api.mdx deleted file mode 100644 index 9580d888..00000000 --- a/docs/SDK-API/context-create.api.mdx +++ /dev/null @@ -1,66 +0,0 @@ ---- -id: context-create -title: "Create a Context" -description: "A POST request for creating a new context and assigning variants to your users." -sidebar_label: "Create a Context" -hide_title: true -hide_table_of_contents: true -api: eJztWF9v2zYQ/yoEnzZAie3YcxI9zU37kHXDgibpBsRBe5JOEluJVEnKsWf4uw9HypbcuF7mpigGLA+JQt4df/f/yCW3kBke3vFYSYtzy+8DnqCJtaisUJKHfMKufr++YRo/1WgsS5VmsUawQmYMmMQH1rAykAkDY0QmaW8GWoC0hlnFFqrWrDaozTEPuKpQA0m/THi4PviCZCIPeAUaSrSoCdaSSyiRh/zPo0mG0vKACwKVIySoecAJltCY8NDqGj/HfpMjuzWoPTNTqUdy/fI14cA5lFVB0iEyJWhbLI5+gRkcXb98zWaD4/7xgAfcxDmWwMMlt4uKiI3VQmZ8tQo66F7JmdBKlodhxJabCckechHnBJWBRqZr6QzqoOO8Qi2I0ByzmxwNshgki5Clqib7y8S7BxOS5HgmLxrt2B8YsQsljSqQGbTkQ7NtiQRnWKiq0eNpuk+qqhCx8+gBukPL/Z11f3h4OETno7eozdfrPvNSnmgApuQW+P4O4EJazBySVOkSrF8aj/hqde/RobEvVLIgnv1gb6WwhiVgwRUAj9GqxtzM5rhVBZrcb6pB4zGSwQia+Wq3TeVUvn///oNRciqXU8nY1Ck95SGbcio070Qy5azXozhh5DVKfoJZr1F4rproiGkEo5PT8TiG8XAwTE7G6ej8/OwnPD0/T9NROjw976fR2RhT6KcxjsaYREOEszRKBwjDUf+sPW0GRf3ZcTnYjUethvijkNnxVK6cFlOKHGc9ackTnaDokYa09si3KvqAsd0KsjtOhxmq4JWmGmsFGmLxyy0vaA0LilaLpfknmW7vkUjP8XmKdJOpcQJfBWTjXbSlkL+izGzOw0HAS5iv/xuP+l1JX+sZylxuhXXCKAj5qrty4eP2jU8H2luRBUylpPHKnvT79Gc7I67rOEZjntd1Ae9kzP+OfIIjty12oGlE4in1uoe5Mh/wpoyROQqRiahA7+5UZI8tuWWb3aV3eOKtJcq6dCV7Y5vhqgvgcDknqwb8XpfivHoXgZSo38WqUJp8u9b1X59dwtx/D05OO4cMVh2rtUIjpQoE2YVD/Yb8WCcCZYy/CVOCjfP9TCkUhriUFpmQULz9BvAbT+8wpayLAqIN+E5Yvtq06MkmLr9Qb3yFaQrOaFeNeQHJeu5+rjoTq4SCuERjINtRD9z+U0aIVsauSam1h9YUX42Og8c63kqoba60+AtdjUkwhbqwuwhp/IlpSkAn9D9vEcdhc0W3oEo5H1dAdZP31rexgBvUs/VdqNYFzZfWVibs9QzIJFLz483l5Vio3mzAabgzGNda2IVjm1TiNdLnfXfrmqzjVVwTtNXTLwSdeffq8sgv7ZtxSSWy/pt2tny1zqhN+7rbHLNuLU1neYYGcU91VKbK6dIYvJ0lL1RRYGyVZpOrS6rvzeAecrrs9fmjq69kv1coJ1eX7LrCWKTrWd0NdJ42QuMGvS+cQhcVYeiLCcNKELJY0E04YQ85SlYbGu5bXiEZsAJkVkOGzTEKDZPKsgValsMMGTBTV5XSlArNVZbiBWKXCY3LHGhPRnWzBFF4x/7cxkusSgrbQsRIlahlvtKq0gIt6IWLXYrOEmSHwl/XGbCLTaRu2W7ZJuc3eEFo4od4elUBQrrphLJj2aTQ1oNGTskV3vHlMgKDt7pYrWj5U43apUXT/VxBv6MQasKbQjURhjaSpuXsUfOHN00u/Mj2vzvsRP+RErDzzOFuETzknK6dB4P43g8Le1XdfjN5HoW/92vCft9uPZQ8v8IHPSE8FXHnmWMLuSe98PiObkhaS/GoLbcckzjGyu6lve80SCohPOBR81xRuq7MNdCTDf0O+ZRPuXtdJAmur7n1JV/XUx5yL5d+/gYMTisZ -sidebar_class_name: "post api-method" -info_path: docs/SDK-API/absmartly-collector-api -custom_edit_url: null ---- - -import ApiTabs from "@theme/ApiTabs"; -import DiscriminatorTabs from "@theme/DiscriminatorTabs"; -import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; -import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; -import MimeTabs from "@theme/MimeTabs"; -import ParamsItem from "@theme/ParamsItem"; -import ResponseSamples from "@theme/ResponseSamples"; -import SchemaItem from "@theme/SchemaItem"; -import SchemaTabs from "@theme/SchemaTabs"; -import Markdown from "@theme/Markdown"; -import OperationTabs from "@theme/OperationTabs"; -import TabItem from "@theme/TabItem"; - -

Create a Context

- - - - - -A POST request for creating a new context and assigning variants to your users. - -## Request - -

Header Parameters

Body

required
- -Units data for which to create the context and variant assignments. Unit types can be found and created in your ABsmartly Web Console settings. - -```json -{ - "type": "user_id" // The name of the unit type - "uid": "4a42766ca6313d26f49985e799ff4f3790fb86efa0fce46edb3ea8fbf1ea3408" // The value of the unit that you are tracking. -} -``` - - -
    units object[]required
  • Array [
  • ]
- -Success - -
Schema
    units object[]required
  • Array [
  • ]
  • assignments object[]required
  • Array [
  • ]
- -Bad request - -
Schema
- -Unauthorized - -
- -Unexpected error - -
Schema
- \ No newline at end of file diff --git a/docs/SDK-API/context-get.api.mdx b/docs/SDK-API/context-get.api.mdx deleted file mode 100644 index 9bbfb422..00000000 --- a/docs/SDK-API/context-get.api.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -id: context-get -title: "Get Context Experiment Data" -description: "A GET request for obtaining data on your experiments." -sidebar_label: "Get Context Experiment Data" -hide_title: true -hide_table_of_contents: true -api: eJzVV21v2zYQ/ivEfVYd243bRp/mviAI+qHBkm4D4qCgpLPNjiJV8ujEM/Tfh6NkS47dZC2KAAMMmCJ5L8/dw+NxAyQXHtIbyK0hvCe4TaBAnztVkbIGUpiK8w/XwuG3gJ7E3DphM5LKKLMQhSQprBFrG5zA+wqdKtGQH0ACtkInWcdFAelW/TkSJFBJJ0skdGx5A0aWCCmgWSlnDSuABBTb/hbQrSEBtq4cFpDOpfZ44KIRPWFBVsyVJnSCligc+qDJi2w9ENdL9ChyaUSGYm6DKYQ0hcgdSsJCqBbJ9K0vpSO9Fn9iJt5Z461G4ZFImUUEh/eyrDR7XeAKta1ar32+xFJCugFaV7zsySmzgLpOdjhlVWmVx9D8OM6e8PPivLu7exTfLXvvK2s8el4fD4f8tw/gKuQ5eg9JwwdDvKUH6eSr532bQzs2+4o57YXoBnqMY95WjjlHqnGgv9jpkc5JjrQiLP1T+lUBSZO1KOC2OQtG0TXLJQ9I6xFZxFda8Sc5OZ+r/KqZ3X61i/Og9Sfzh3RKRtleGDhAq2aBhzIUCk2OveEVOZXTIWhV9DApQ7hA10/jaPyybiEd5LCfbbyvvmTSGHRfcqutg7ofgUdNDOtegB41Ejy6L6pg3f0wPipTOVuEPHpRt/E+5s3culJSM/XqtK/h7HTy8tXr09Hrs8n4Tb3N1dMEMaHM9lUXNmQao/db5TfDwSQZDia39X7yf8zFF5NX49PR5Gz05s3Z2XBSP6DOL/M1GbGf+zx8ytOXY0igVEaVoYR0mEAp75vxaPy6T7T6AaN/8ghGqh7Q/GkC32HmFSEXXiBFce7DriJMeyWYd+wO2zN7SVyQI+nrWBLnanFMwAStJecvJRewr2Azg3g+Z5DOwGExg/o7kLcJ5tVdQXnUuY2YQXO/zCAVN/y5oN1wJeP0DOQCZyDqRDSzOiDPj4eivo0/qA/KVmc2s1ajNH278ebrY3jXtA4dFKiPLJ8j/d7eP7xeJ3B67AZ6K4ttL/OrbqHcFlyaS/ReLo7QIK7/hwpQdzqO9Q9dTp3jgtxiHB1i/GxkoKV16h+MxbXAuQyajm3kSzLnlgCj0v99RKIELS23nIu216QlpHCy7W/50nCrbesZnIYUlkSVT09OvDRFZu8HMmv7ooGyJ6sRcHPjMQ9O0TqKTSv1EXl421+64uA0CLcbunLSTGzvXvjrxfTy4kUzFVvAJcoixqALJB92RqTM3EZVLdyubXtntcacrBPTywtuGtD5JrWjwXAwhCMN5KcKzfTyQlxVmKv5rpVcShLN3gx97Ce/Y4WbS+V5JJQXpVRGr0XwWIi7JRoRPL8LOlllhBRamkWQC2zNWPTCWBJrJLGUKxRS+FBV1jERr95/HLQ8lE2paCMWnW62cbkopdJNXH/r0pXbkkmjVY5cBzrhS2crp5CkW0fmVNZTKU1vxzmSaEuJ6EqNeC9JPgzjpjslP/06amnB5k4qLVVsZyIbNy1l955kS+uJpzabTHr87HRd83TzbmBGFsrzDfGdl8Oex8/+WDqK9W8+Hg/a53h7QArAr6UfQvTMz6JHEO2/7jpEt22XEa/xG2682hPP2WtEp3mOVT8OBxWYtezq2/mHa6jrfwH7Smgm -sidebar_class_name: "get api-method" -info_path: docs/SDK-API/absmartly-collector-api -custom_edit_url: null ---- - -import ApiTabs from "@theme/ApiTabs"; -import DiscriminatorTabs from "@theme/DiscriminatorTabs"; -import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; -import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; -import MimeTabs from "@theme/MimeTabs"; -import ParamsItem from "@theme/ParamsItem"; -import ResponseSamples from "@theme/ResponseSamples"; -import SchemaItem from "@theme/SchemaItem"; -import SchemaTabs from "@theme/SchemaTabs"; -import Markdown from "@theme/Markdown"; -import OperationTabs from "@theme/OperationTabs"; -import TabItem from "@theme/TabItem"; - -

Get Context Experiment Data

- - - - - -A GET request for obtaining data on your experiments. - -## Request - -

Query Parameters

- -Success - -
Schema
    experiments object[]required
  • Array [
  • applications object[]required
  • Array [
  • ]
  • variants object[]required
  • Array [
  • ]
  • ]
- -Bad request - -
Schema
- -Unauthorized - -
- -Unexpected error - -
Schema
- \ No newline at end of file diff --git a/docs/SDK-API/context-publish-batch.api.mdx b/docs/SDK-API/context-publish-batch.api.mdx deleted file mode 100644 index c91876b1..00000000 --- a/docs/SDK-API/context-publish-batch.api.mdx +++ /dev/null @@ -1,134 +0,0 @@ ---- -id: context-publish-batch -title: "Publish Experiment Events for Multiple Contexts" -description: "A PUT request for publishing your exposures, goals and attributes from multiple contexts." -sidebar_label: "Publish Experiment Events for Multiple Contexts" -hide_title: true -hide_table_of_contents: true -api: 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 -sidebar_class_name: "put api-method" -info_path: docs/SDK-API/absmartly-collector-api -custom_edit_url: null ---- - -import ApiTabs from "@theme/ApiTabs"; -import DiscriminatorTabs from "@theme/DiscriminatorTabs"; -import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; -import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; -import MimeTabs from "@theme/MimeTabs"; -import ParamsItem from "@theme/ParamsItem"; -import ResponseSamples from "@theme/ResponseSamples"; -import SchemaItem from "@theme/SchemaItem"; -import SchemaTabs from "@theme/SchemaTabs"; -import Markdown from "@theme/Markdown"; -import OperationTabs from "@theme/OperationTabs"; -import TabItem from "@theme/TabItem"; - -

Publish Experiment Events for Multiple Contexts

- - - - - -A PUT request for publishing your exposures, goals and attributes from multiple contexts. - -## Request - -

Header Parameters

Body

required
- -An array of data to publish. - -**Hashed** - -The hashed value describes whether your values have already been hashed, or if they are to be hashed by the Collector. - -**Historic** - -The historic value tells the Collector whether this is new or old data. - -**Published At** - -The publishedAt value is the time at which the request was made. - -**Units** - -Units are the values which are used to choose the variant -assignments for each user. Unit types can be found and created in -your ABsmartly Web Console settings. The payload takes the form of: - -```json -{ - "type": "user_id" // The name of the unit type - "uid": "4a42766ca6313d26f49985e799ff4f3790fb86efa0fce46edb3ea8fbf1ea3408" // The value of the unit that you are tracking. -} -``` - -**Exposures** - -Exposures tell the collector information about which variant of an experiment was shown to the user, and when: - -```json -{ - "id": 3, // The ID of the exposed experiment. - "name": "exp_banner_color", // The name of the exposed experiment. - "unit": "user_id", // The unit that was used together with the experiment seed to generate the variant. - "variant": 1, // The variant that was shown. - "exposedAt": 1609244179528, // The time at which the exposure happened. - "assigned": true, // Whether the user was exposed to the experiment in this specific request, it could be that the user was not assigned because it doesn’t match the audience, or the experiment is already fullOn, or the variant was overriden, etc. - "eligible": true, // Whether the experiment is in the right part of the traffic allocation to this experiment and can be triggered. - "overridden": false, // Whether the variant was overridden or not. - "fullOn": false, // True if this experiment is fullOn and the winning variant is being forced to everyone. - "custom": false, // Whether this variant was a custom assignment. - "audienceMismatch": false // Whether this variant was shown outside of it’s specified target audience. -} -``` - -**Goals** - -Goals are used to track various metrics that are related to your -experiment. Goals can be created and found in your ABsmartly Web -Console settings: - -```json -{ - "name": "banner_click", // The name of the goal that you are tracking. - "achievedAt": 1609254179528, // The time that the goal was achieved. - "properties": {} // Any properties that you wish to pass along with this goal. -} -``` - -**Attributes** - -Attributes allow for segmentation of your data on the Web Console: - -```json -{ - "name": "age", // The name of the attribute. - "value": 39, // The attribute's value. - "setAt": 1609244179528 // The time at which the value was set. -} -``` - - -
    requests object[]required
    - -**Possible values:** `>= 1`, `<= 500` - -
  • Array [
  • units object[]required
  • Array [
  • ]
  • exposures object[]
  • Array [
  • ]
  • goals object[]
  • Array [
  • ]
  • attributes object[]
  • Array [
  • ]
  • ]
- -Success - -
Schema
    warnings object[]
  • Array [
  • ]
  • errors object[]
  • Array [
  • ]
- -Bad request - -
Schema
    warnings object[]
  • Array [
  • ]
  • errors object[]
  • Array [
  • ]
- -Unauthorized - -
- -Unexpected error - -
Schema
- \ No newline at end of file diff --git a/docs/SDK-API/context-publish.api.mdx b/docs/SDK-API/context-publish.api.mdx deleted file mode 100644 index 935b39bc..00000000 --- a/docs/SDK-API/context-publish.api.mdx +++ /dev/null @@ -1,130 +0,0 @@ ---- -id: context-publish -title: "Publish Experiment Events" -description: "A PUT request for publishing your exposures, goals and attributes." -sidebar_label: "Publish Experiment Events" -hide_title: true -hide_table_of_contents: true -api: eJztWm1v2zgS/isEv9xdobw4SdPEn87tBru57mKDNrk9oA5aShpJ3EiklqTs+AID+zf27+0vOQxf9GI7qdcN0PvQfkgtijOceeaFM6QeqGG5puMPNJHCwL2htxFNQSeK14ZLQcd0Qq5uromC3xrQhmRSkbqJS64LLnKykI0icF9L3SjQEcklKzVhIiXMGMXjxoDepxGVNSiGDC9TOg5rXTk+NKI1U6wCAwpFeaCCVUDH9D97kxyEoRHlKEgBLAVFI4qycAUpHRvVwKq81wWQGw3KEROZOSHff/cWBYF7VtUlcmexrpgy5WLvX2zG9t5/95bMRvuH+yMaUZ0UUDE6fqBmUeNkbRQXOV0uo550F2LGlRTVbjJCR024IPOCJwWKSpgCohoh+viC4jhR75PrAjSQhAkSA8lkg1CLlCQKmIEUOVmayWuvHfkFYvJGCi1LIBqM4SLXQyRSmEEpa6/HdrpP6rrkiTXpDrqzjvor6z6fz3fRee/foPSX6z5zXLYEgEgxEP5wg+BcGMitJJlUFTNu6PSELpe3TjrQ5rVMF0jzeWFTZhgxEvH2UQ/p/lRMxYsXPzB8ePECn3BqYZ/JjJUNEMcpBk3mBZgClFPGvtSkYDMgrFTA0gWJAYQnjohUhGfEFLCwSLiVPed4gS/IG1mWkBipghxcG6l40pPEj3hZDJSlHpK2UpmCa8I1ETDHtWWZWpU966ugMpmYjn0LxMT4Fbhjb3gFhBlvTRwJWXPONKlYCp7vjeBGO4b2p9O1gICPY4CDjYYUUUgKKXWYozgTZiqY1jwXzjMwLQNLCiRQ+wS5EvQI/VS0TMU24UKszmxRSpYSw+7AKYvuRWQ2RiU+ffr0q5ZiKh6mgpCp9cUpHZMpRXE+8nRKycGBZYTBhDkZWTRBSkfV4DwkOmEnR69OTxN2ejw6To9Os5Pz87OX8Or8PMtOsuNX54dZfHYKGTvMEjg5hTQ+BnaWxdkI2PHJ4Vm3mjPPYLmCmTbQjGLJHRf5/lQsrRbOPBdhP3Mmah+tJ1lWSetIXLg4wyhmsWyC9b2VcG0mekFsXUEXci7QrFYsDSqylpkXIDbi6YA5joJal98FnezWC2lvgX1Hgjg7NOG+/hgzIUB9TGQp1ZRGm4zxKCeEbcWYLYMOUlTLO2vuQmvOTRE4B+U1OHfOQWA9MHBov1xwbzomo6izo0OzXcoi6Cm85BNHc3p4fnRyMnp1/vLorKVfj8xQs5CC1TUIm9WQmQsqsIDbpIgsfmmzhTOXFSEA5s3Y05ILl1d0DQnPeBLSQES4IYlsyhQj0uoy4CikIWF9EkPCGg1IkkrQ4s/f/zCkYsbLz5qUg0jApszV9XWbXLOmLH8W7aSAI64mZ6AUT0FEBEwSsCx5zuMSHlV/uIzVFIjieWFIzZQJ3mQUy1BzVpbS73UWJ677HGw6cvnJKJ7noFo7eOlSEChKxkq9LssGbVIQqKuQwZ0cAEMe1wpzdrYmDtceLysYrjDnbicOK3FNYsCBTKrE2R5moBZSgF8vabSR1WMycz0QmhE3nXSpPLihN+9PXFubtwyf5OfyimyM5qkNbG7+/P2P1hFRYKZyMK33rCS+77F6d0nve1fI97YgmyztcrLRpAKjeKKdF9uiBUq7rRhpt/qp6CUS4rh5U4cNCEF229LGwm0qVreijbmxS3QhyZU8uXskyWF78ugWYHFPCg6zQTJ5uTGZtNFrWVpjelLPqVbY8xgOGjk9LJF6IhakG+8EmXNdIHA10xi6UuQhe3JtF1ix06TtrZyxumcbcHNbDmjIEXwXfKELsvWcdFHb2+0/gyzL4RFA2y6vzd5lY4mOz9v57Zy/abch+7kazIac/XjKdpu59XMwPURo5BpKYbCm7ZXXB6gOjq1VyTL+FRIzKNc/2I1OYzPa1XfYDXcGQwauFu2xiqUsgaEQoilLFmNhHqrpjDWloWMbuMuIhrp0N+q+WFvU+70+YYDvMvKKdjyYUmyBnYyBSn8OJftuDRZHsdo+9RstXzxQXJ+nm+ZWXPwIIjcFHY8iWrH78HR6ctjn9KXlIXZ11HBjmWGlbAfaQ4y/AsywYfoBylKSuVRlugIaxwHbR0ahwKFRV7jQqK07cNjvwesoD3DbbPnjI4ckr5rKdogtbsdLL8KTZlqtFqn3l01Uqy670dhB3b8seMXu3e/R0VnfmZd94L4sEFrQNwVkS4XKLXtm2WZyV448PT0Et6s7tpvraobt5q7WEdtQ9aIjtD42QuzZ3q5pwzt/t7+ue/fnnbO/w6Nv9bjt4AgvO0fYlMw6PYZ+3scH65qJE8KenuG77uDzC7Gy++MuMLEcXOSVjZ3ZpYDzNWXCMl8SSD1A2kqELvvD/iDlneuD8N0SVda1FNppdXR4iP8NE+r7JklA6+fa4OXdOprybkNILCM6Zwor/51tGGO0XYoU7hG3GQgTHnQT5legNdpqTage8bpdlgN+G9+HJdbPM7tFN511rtvLWegnT2P3SaWk+gbLEJbH53hfP9nk3q9ZGo4Gvrn4/40tv7n4ri4+WnfxG8EaU0jF/wu2Gmy7mvWJeF6Q4LmAhf+5AiKRKTwFuH2/zfXJlvhdWOGXDpIKTCHxwrNujL3lxG6GHoSrVtx71SxcejaqxIskY2o9PjjQTKSxvN9vbyn3uTyYjSje4mhIGsXNwpJNav4W8Odt/9V7BMdpGCZ03uwGot7F1tXlnht66jILNULw33WXSBehIOgaY3fs1et1/cCgfR2e0oaG9EMrYugffK/4DC3f7aDD++B6qeMWg7W2J3Q9PVHaTmY06EBWdOl6Ct8UtW2De+53Bh6aUPz7x1Df+8f1Et6V6bdtRd7dmA8K5GF9PDzLGkaBvRvs160dR3T4tpTE+tGXi8MK8HaJrpNJ62WhFGwP87prt8nVJXLzd6djivfth2t99ESQn2sQk6tL8t4fofsjZDww664W8VDokVXw1opr/IVnthXjoly4k0y8ZCGNxkPcjpYLwkjJRN6w3J/t4aG7PZFfgPEXlkQ3dS0V5ij/NQFGMnPp1uNlhXbTMP1XjJcu5P7ZRXIiK8wnJU8A02dHfKVkrTgYphY2qdRSm4qJ/gwXReSiO7W+wC1Br4L40KXP5/mCw0cmJq6DumTclhA2Zz34xDb4hqSQ2uDQw0PMNNyocrnE4d8aUDZZ+XCygfEB3ccnHXS9lGt80SWTRzX7+zufof5Bnv7sY6P0d5gWe1+ZeC+nFG/9dxbia3/X8aSqw09Wnkfhr/0xx9O2HXyn8vwK7/QFx7YS974yGUjupr5x8u1dI7duxlqt1FFMkgRq8+Tc217VcnVzTSMa+49FKlspUcXwgxn8O6ZTOqX24y5kYIsNO/5AQyqlY+rY4r//Ad/qOJw= -sidebar_class_name: "put api-method" -info_path: docs/SDK-API/absmartly-collector-api -custom_edit_url: null ---- - -import ApiTabs from "@theme/ApiTabs"; -import DiscriminatorTabs from "@theme/DiscriminatorTabs"; -import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; -import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; -import MimeTabs from "@theme/MimeTabs"; -import ParamsItem from "@theme/ParamsItem"; -import ResponseSamples from "@theme/ResponseSamples"; -import SchemaItem from "@theme/SchemaItem"; -import SchemaTabs from "@theme/SchemaTabs"; -import Markdown from "@theme/Markdown"; -import OperationTabs from "@theme/OperationTabs"; -import TabItem from "@theme/TabItem"; - -

Publish Experiment Events

- - - - - -A PUT request for publishing your exposures, goals and attributes. - -## Request - -

Header Parameters

Body

required
- -The data to be published. - -**Hashed** - -The hashed value describes whether your values have already been hashed, or if they are to be hashed by the Collector. - -**Historic** - -The historic value tells the Collector whether this is new or old data. - -**Published At** - -The publishedAt value is the time at which the request was made. - -**Units** - -Units are the values which are used to choose the variant -assignments for each user. Unit types can be found and created in -your ABsmartly Web Console settings. The payload takes the form of: - -```json -{ - "type": "user_id" // The name of the unit type - "uid": "4a42766ca6313d26f49985e799ff4f3790fb86efa0fce46edb3ea8fbf1ea3408" // The value of the unit that you are tracking. -} -``` - -**Exposures** - -Exposures tell the collector information about which variant of an experiment was shown to the user, and when: - -```json -{ - "id": 3, // The ID of the exposed experiment. - "name": "exp_banner_color", // The name of the exposed experiment. - "unit": "user_id", // The unit that was used together with the experiment seed to generate the variant. - "variant": 1, // The variant that was shown. - "exposedAt": 1609244179528, // The time at which the exposure happened. - "assigned": true, // Whether the user was exposed to the experiment in this specific request, it could be that the user was not assigned because it doesn’t match the audience, or the experiment is already fullOn, or the variant was overriden, etc. - "eligible": true, // Whether the experiment is in the right part of the traffic allocation to this experiment and can be triggered. - "overridden": false, // Whether the variant was overridden or not. - "fullOn": false, // True if this experiment is fullOn and the winning variant is being forced to everyone. - "custom": false, // Whether this variant was a custom assignment. - "audienceMismatch": false // Whether this variant was shown outside of it’s specified target audience. -} -``` - -**Goals** - -Goals are used to track various metrics that are related to your -experiment. Goals can be created and found in your ABsmartly Web -Console settings: - -```json -{ - "name": "banner_click", // The name of the goal that you are tracking. - "achievedAt": 1609254179528, // The time that the goal was achieved. - "properties": {} // Any properties that you wish to pass along with this goal. -} -``` - -**Attributes** - -Attributes allow for segmentation of your data on the Web Console: - -```json -{ - "name": "age", // The name of the attribute. - "value": 39, // The attribute's value. - "setAt": 1609244179528 // The time at which the value was set. -} -``` - - -
    units object[]required
  • Array [
  • ]
  • exposures object[]
  • Array [
  • ]
  • goals object[]
  • Array [
  • ]
  • attributes object[]
  • Array [
  • ]
- -Success - -
Schema
    warnings object[]
  • Array [
  • ]
  • errors object[]
  • Array [
  • ]
- -Bad request - -
Schema
    warnings object[]
  • Array [
  • ]
  • errors object[]
  • Array [
  • ]
- -Unauthorized - -
- -Unexpected error - -
Schema
- \ No newline at end of file diff --git a/docs/SDK-API/experiment-get.api.mdx b/docs/SDK-API/experiment-get.api.mdx deleted file mode 100644 index c6aff410..00000000 --- a/docs/SDK-API/experiment-get.api.mdx +++ /dev/null @@ -1,50 +0,0 @@ ---- -id: experiment-get -title: "Get Experiment Data" -description: "A GET request for obtaining data on all running experiments." -sidebar_label: "Get Experiment Data" -hide_title: true -hide_table_of_contents: true -api: eJzFVktv20YQ/iuDObUArUea9MBT1dgwXB9qRHZawDaCETkSN1nuMrtL2arA/14MSYuUpdiGYsAnUbvz+Gb2m8caAy08xtfI9wU7lbMJeBuhLdhRUNacpRj37k45YIQp+8SpQu4xxgmcnlyC4+8l+wBz68DOAimjzAJSCgTWAGkNrjT1WWfNDzDCghzlHNgJjDUayhlj/PdoshAsESrxkTGl7DBCcaMcpxgHV/JjKJcZw5Vn1yiDncPKlg6mx+fiie8pL7RYp5nPyQW9OvqLlnQ0PT6H5XgwGowxQp9knBPGawyrQoR9cMossKqiHroTs1TOmvwwjNxpgzJwl6kkE6hAjjd5qqH3kwWXGXuGhAzMGOa2NCmQSSFxTIFTsVTrTP5so4N/eAYfrfFWM3gOQZmF385EykvWtmjjeFnsk6LQKqnpcUDs1Gm/cex3d3eHxHz0mZ3/+diXjZUXJgCs2QI/2gNcmcCLGsncupxCc/T7e6yqW0HnC2s8e9F4NxrJzzbCaZkk7D1GmFgThBHxGnuQh1+9yK13PdvZV07CVgqu0X6rAW9CkL5SOOksQTUo+pedMXKOVpLcwLl/zolKMWpeqVZwD6z0hVYiGxzN5yqZtn+X5BTtxaLSvZncJHz87req9bRDlT6p+L74MiNj2H1JrLYOqz6wJ12MqgfczyfDlPls+6lTW840i7uNwevR4EM0Gny4rR4l4tXsR2OxvcnqgY9YZ3XnRZ7PdZDir1tXVXN2rhb7FEypNQn2ti47A+sbrB/pBuMbdJzeYCV1j0GF+v5kQ9DPTYhY7b/+0bn/1FadCFQRvh+Nd+vuylAZMuvUf5xKJCnPqdRhn6BUTCL9jp2z7rUqNbGp1E/O3tNiz0vU9y/pM52Nfe20y08NvmpSknPIrGwZi3q3KChkGOOwt49E6NktHxaE0mlpuiEUPh4OPZl0Zu8Hm4k+UHa4HKN0PM9J6VRY1WqTQp2zfN72r6aSnybIB4GOws1B1BsCF2dHzdFTjV+CUmZua1NtxN1Y+mi15iRYB5OLM+lI7TCJURaQ0e52ZeDvgs3k4gymBSdq/jA/QkYBGtkZewgZww+8yPBUXr5AechJGb2C0nMKdxkbKL0MnE5XGSDQZBYlLbh1Y9mDsQFWHCCjJQOBL4vCOuFiu14JFSkJXeliDboRk7rNSekmr390z5XYXHijVcJSJp3yhbOFUxzIrWryFNaHnExP4pQDdKUGxxTocfrWXYH87J7asiLwfRgWmpQR2DUZ1y1pHy/RmfVBTtfrGXm+crqq5Ph7ya4mYts46850LX20JZTQNVVeLlKM56T942WiH9Yvn1r2/QpPr797A/gmlO9t20vSpUihbD8Hg3jr/fbJULdX99cJ+K2X2qffdmtff/2AD9pkX4q4t21vIW9EJ0nCRf8Zd4agdPvNiDk9ucSq+h/MJSsy -sidebar_class_name: "get api-method" -info_path: docs/SDK-API/absmartly-collector-api -custom_edit_url: null ---- - -import ApiTabs from "@theme/ApiTabs"; -import DiscriminatorTabs from "@theme/DiscriminatorTabs"; -import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint"; -import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes"; -import MimeTabs from "@theme/MimeTabs"; -import ParamsItem from "@theme/ParamsItem"; -import ResponseSamples from "@theme/ResponseSamples"; -import SchemaItem from "@theme/SchemaItem"; -import SchemaTabs from "@theme/SchemaTabs"; -import Markdown from "@theme/Markdown"; -import OperationTabs from "@theme/OperationTabs"; -import TabItem from "@theme/TabItem"; - -

Get Experiment Data

- - - - - -A GET request for obtaining data on all running experiments. - -## Request - -

Header Parameters

- -Success - -
Schema
    experiments object[]required
  • Array [
  • variants object[]required
  • Array [
  • ]
  • ]
- -Unauthorized - -
- -Unexpected error - -
Schema
- \ No newline at end of file diff --git a/docs/SDK-API/sidebar.js b/docs/SDK-API/sidebar.js deleted file mode 100644 index 744c39bc..00000000 --- a/docs/SDK-API/sidebar.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = []; \ No newline at end of file diff --git a/src/anchorRedirects.ts b/src/anchorRedirects.ts index 61417673..595becc7 100644 --- a/src/anchorRedirects.ts +++ b/src/anchorRedirects.ts @@ -8,13 +8,14 @@ interface AnchorRedirects { }; } +// All paths are stored in lowercase for case-insensitive matching const ANCHOR_REDIRECTS: AnchorRedirects = { + // ============================================================================= // NEW paths (after server redirect) - ONLY anchors that transform or move + // ============================================================================= '/docs/web-console-docs/experiments/creating-an-experiment': { - // Same-page anchor renames 'application': 'applications', 'targeting-audiences': 'audiences', - // Cross-page redirects (content moved to different pages) 'error-control': '/docs/web-console-docs/experiments/setting-up-a-gst-experiment#error-control', 'sample-size-calculation': '/docs/web-console-docs/experiments/setting-up-a-gst-experiment#what-is-the-experiment-duration-based-on', 'type-of-analysis': '/docs/web-console-docs/experiments/overview#analysis-methods', @@ -25,8 +26,45 @@ const ANCHOR_REDIRECTS: AnchorRedirects = { 'application': 'audiences', 'targeting-audiences': 'audiences', }, + '/docs/web-console-docs/experiments/templates': { + 'introduction': 'overview', + }, + '/docs/web-console-docs/users-teams-permissions/teams': { + 'creating-a-team': 'create-a-team', + 'viewing-the-company-hierarchy': 'viewing-the-team-hierarchy', + }, + '/docs/web-console-docs/configuration/settings': { + 'applications': '/docs/web-console-docs/Configuration/Applications', + 'units': '/docs/web-console-docs/Configuration/Units', + 'goals': '/docs/web-console-docs/goals-and-metrics/goals/overview', + 'metrics': '/docs/web-console-docs/goals-and-metrics/metrics/overview', + 'teams': '/docs/web-console-docs/Users-teams-Permissions/Teams', + }, + '/docs/web-console-docs/experiments/overview': { + 'fixed-horizon-testing': 'fixed-horizon', + 'group-sequential-testing': 'group-sequential', + 'which-analysis-type-should-i-choose-for-my-experiment': 'how-to-choose', + }, + '/docs/web-console-docs/goals-and-metrics/metrics/overview': { + 'primary-metric': 'role', + 'secondary-metrics': 'role', + 'guardrail-metrics': 'role', + 'exploratory-metrics': 'role', + 'business': 'purpose', + 'behavioural': 'purpose', + 'operational': 'purpose', + 'binomial': 'data-structure', + 'continuous': 'data-structure', + 'short-term': 'time-horizon', + 'long-term': 'time-horizon', + 'proxy': 'functionality', + 'composite': 'functionality', + }, + + // ============================================================================= // OLD paths (for local testing and fallback) - redirect to new structure // Only include anchors that TRANSFORM - browser preserves unchanged anchors automatically + // ============================================================================= '/docs/web-console-docs/creating-an-experiment': { 'application': '/docs/web-console-docs/experiments/creating-an-experiment#applications', 'targeting-audiences': '/docs/web-console-docs/experiments/creating-an-experiment#audiences', @@ -40,13 +78,51 @@ const ANCHOR_REDIRECTS: AnchorRedirects = { 'application': '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', 'targeting-audiences': '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', }, + '/docs/web-console-docs/templates': { + 'introduction': '/docs/web-console-docs/experiments/templates#overview', + }, + '/docs/web-console-docs/managing-teams': { + 'creating-a-team': '/docs/web-console-docs/Users-teams-Permissions/Teams#create-a-team', + 'viewing-the-company-hierarchy': '/docs/web-console-docs/Users-teams-Permissions/Teams#viewing-the-team-hierarchy', + }, + '/docs/web-console-docs/creating-and-managing-teams': { + 'creating-a-team': '/docs/web-console-docs/Users-teams-Permissions/Teams#create-a-team', + 'viewing-the-company-hierarchy': '/docs/web-console-docs/Users-teams-Permissions/Teams#viewing-the-team-hierarchy', + }, + '/docs/web-console-docs/settings': { + 'applications': '/docs/web-console-docs/Configuration/Applications', + 'units': '/docs/web-console-docs/Configuration/Units', + 'goals': '/docs/web-console-docs/goals-and-metrics/goals/overview', + 'metrics': '/docs/web-console-docs/goals-and-metrics/metrics/overview', + 'teams': '/docs/web-console-docs/Users-teams-Permissions/Teams', + }, + '/docs/web-console-docs/types-of-analysis': { + 'fixed-horizon-testing': '/docs/web-console-docs/experiments/overview#fixed-horizon', + 'group-sequential-testing': '/docs/web-console-docs/experiments/overview#group-sequential', + 'which-analysis-type-should-i-choose-for-my-experiment': '/docs/web-console-docs/experiments/overview#how-to-choose', + }, + '/docs/web-console-docs/understanding-experimentation-metrics': { + 'primary-metric': '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', + 'secondary-metrics': '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', + 'guardrail-metrics': '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', + 'exploratory-metrics': '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', + 'business': '/docs/web-console-docs/goals-and-metrics/metrics/overview#purpose', + 'behavioural': '/docs/web-console-docs/goals-and-metrics/metrics/overview#purpose', + 'operational': '/docs/web-console-docs/goals-and-metrics/metrics/overview#purpose', + 'binomial': '/docs/web-console-docs/goals-and-metrics/metrics/overview#data-structure', + 'continuous': '/docs/web-console-docs/goals-and-metrics/metrics/overview#data-structure', + 'short-term': '/docs/web-console-docs/goals-and-metrics/metrics/overview#time-horizon', + 'long-term': '/docs/web-console-docs/goals-and-metrics/metrics/overview#time-horizon', + 'proxy': '/docs/web-console-docs/goals-and-metrics/metrics/overview#functionality', + 'composite': '/docs/web-console-docs/goals-and-metrics/metrics/overview#functionality', + }, }; function handleAnchorRedirect(): void { - const path = window.location.pathname.replace(/\/$/, ''); // Remove trailing slash + // Normalize path to lowercase for case-insensitive matching + const path = window.location.pathname.replace(/\/$/, '').toLowerCase(); const hash = window.location.hash.slice(1); - // Early return if no anchor present - no need to check redirects if (!hash) return; const redirects = ANCHOR_REDIRECTS[path]; @@ -58,15 +134,13 @@ function handleAnchorRedirect(): void { if (newDestination.startsWith('/')) { window.location.replace(newDestination); } else { - window.location.replace(`${path}#${newDestination}`); + window.location.replace(`${window.location.pathname}#${newDestination}`); } } if (typeof window !== 'undefined') { - // Run on initial load handleAnchorRedirect(); - // Also run after client-side navigation if (window.addEventListener) { window.addEventListener('load', handleAnchorRedirect); window.addEventListener('hashchange', handleAnchorRedirect); diff --git a/static/_redirects b/static/_redirects index 92b7567e..79255954 100644 --- a/static/_redirects +++ b/static/_redirects @@ -1,34 +1,128 @@ -# Netlify Redirects - Server-side 302 redirects for URL structure changes (temporary for testing) +# Netlify Redirects - Server-side 302 redirects for URL structure changes # Format: from to [status-code] # NOTE: Change to 301 (permanent) once verified all redirects work correctly -# Anchor redirects are handled client-side via JavaScript - -# Base path redirects (browser should preserve matching anchors) -# Note: Adding trailing slashes to match Docusaurus URL normalization - -# SDK Documentation moves (docs/SDK-Documentation/* → docs/APIs-and-SDKs/SDK-Documentation/*) -/docs/SDK-Documentation/Advanced/code-as-a-variant-variable /docs/APIs-and-SDKs/SDK-Documentation/Advanced/code-as-a-variant-variable/ 302 -/docs/SDK-Documentation/Advanced/context-attributes /docs/APIs-and-SDKs/SDK-Documentation/Advanced/context-attributes/ 302 -/docs/SDK-Documentation/Advanced/custom-assignments /docs/APIs-and-SDKs/SDK-Documentation/Advanced/custom-assignments/ 302 -/docs/SDK-Documentation/Advanced/finalize /docs/APIs-and-SDKs/SDK-Documentation/Advanced/finalize/ 302 -/docs/SDK-Documentation/Advanced/publish /docs/APIs-and-SDKs/SDK-Documentation/Advanced/publish/ 302 -/docs/SDK-Documentation/Advanced/tracking-goals /docs/APIs-and-SDKs/SDK-Documentation/Advanced/tracking-goals/ 302 -/docs/SDK-Documentation/Advanced/using-custom-fields-in-your-code /docs/APIs-and-SDKs/SDK-Documentation/Advanced/using-custom-fields-in-your-code/ 302 -/docs/SDK-Documentation/basic-usage /docs/APIs-and-SDKs/SDK-Documentation/basic-usage/ 302 -/docs/SDK-Documentation/getting-started /docs/APIs-and-SDKs/SDK-Documentation/getting-started/ 302 +# Using splat (*) patterns where possible to reduce duplication + +# ============================================================================= +# SDK Documentation (docs/SDK-Documentation/* → docs/APIs-and-SDKs/SDK-Documentation/*) +# ============================================================================= +# Explicit base path redirects (splats don't match bare paths without trailing slash) +/docs/SDK-Documentation/Advanced /docs/APIs-and-SDKs/SDK-Documentation/Advanced/ 302 /docs/SDK-Documentation /docs/APIs-and-SDKs/SDK-Documentation/ 302 +/docs/sdk-documentation/advanced /docs/APIs-and-SDKs/SDK-Documentation/Advanced/ 302 +/docs/sdk-documentation /docs/APIs-and-SDKs/SDK-Documentation/ 302 + +# Splat patterns handle all subpaths - both PascalCase and lowercase +/docs/SDK-Documentation/Advanced/* /docs/APIs-and-SDKs/SDK-Documentation/Advanced/:splat 302 +/docs/SDK-Documentation/* /docs/APIs-and-SDKs/SDK-Documentation/:splat 302 +/docs/sdk-documentation/advanced/* /docs/APIs-and-SDKs/SDK-Documentation/Advanced/:splat 302 +/docs/sdk-documentation/* /docs/APIs-and-SDKs/SDK-Documentation/:splat 302 + +# Old root-level getting-started +/docs/getting-started /docs/APIs-and-SDKs/SDK-Documentation/getting-started/ 302 + +# ============================================================================= +# Examples (docs/Examples/* → docs/APIs-and-SDKs/Web-Console-API/Examples/*) +# ============================================================================= +/docs/Examples /docs/APIs-and-SDKs/Web-Console-API/Examples/ 302 +/docs/examples /docs/APIs-and-SDKs/Web-Console-API/Examples/ 302 +/docs/Examples/* /docs/APIs-and-SDKs/Web-Console-API/Examples/:splat 302 +/docs/examples/* /docs/APIs-and-SDKs/Web-Console-API/Examples/:splat 302 + +# ============================================================================= +# Onboarding/SSO → Third-party-integrations/SSO +# (Cannot use splats due to different naming patterns) +# ============================================================================= +/docs/onboarding/google%20saml%20setup /docs/Third-party-integrations/SSO/Google%20SAML%20Setup/ 302 +/docs/onboarding/azure%20saml%20setup /docs/Third-party-integrations/SSO/Azure%20SAML%20Setup/ 302 +/docs/onboarding/okta%20saml%20setup /docs/Third-party-integrations/SSO/Okta%20SAML%20Setup/ 302 +/docs/onboarding/google-saml-setup /docs/Third-party-integrations/SSO/Google%20SAML%20Setup/ 302 +/docs/onboarding/azure-saml-setup /docs/Third-party-integrations/SSO/Azure%20SAML%20Setup/ 302 +/docs/onboarding/okta-saml-setup /docs/Third-party-integrations/SSO/Okta%20SAML%20Setup/ 302 +/docs/Onboarding/Google%20SAML%20Setup /docs/Third-party-integrations/SSO/Google%20SAML%20Setup/ 302 +/docs/Onboarding/Azure%20SAML%20Setup /docs/Third-party-integrations/SSO/Azure%20SAML%20Setup/ 302 +/docs/Onboarding/Okta%20SAML%20Setup /docs/Third-party-integrations/SSO/Okta%20SAML%20Setup/ 302 +/docs/web-console-docs/SSO/* /docs/Third-party-integrations/SSO/:splat 302 + +# ============================================================================= +# API paths → APIs-and-SDKs/SDK-API +# ============================================================================= +/docs/API /docs/APIs-and-SDKs/SDK-API/ 302 +/docs/sdk-api /docs/APIs-and-SDKs/SDK-API/ 302 +/docs/SDK-API /docs/APIs-and-SDKs/SDK-API/ 302 +/docs/API/* /docs/APIs-and-SDKs/SDK-API/:splat 302 +/docs/sdk-api/* /docs/APIs-and-SDKs/SDK-API/:splat 302 +/docs/SDK-API/* /docs/APIs-and-SDKs/SDK-API/:splat 302 + +# ============================================================================= +# Web Console API (docs/web-console-api/* → docs/APIs-and-SDKs/Web-Console-API/*) +# ============================================================================= +# IMPORTANT: Specific rules must come BEFORE splat rules (first match wins) -# Examples moves (docs/Examples/* → docs/APIs-and-SDKs/Web-Console-API/Examples/*) -/docs/Examples/Slack-Integration /docs/APIs-and-SDKs/Web-Console-API/Examples/Slack-Integration/ 302 +# Old naming convention (get-*, list-* → *-get, *-list) - must be before splat +/docs/web-console-api/get-api-key /docs/APIs-and-SDKs/Web-Console-API/api-key-get/ 302 +/docs/web-console-api/get-application /docs/APIs-and-SDKs/Web-Console-API/application-get/ 302 +/docs/web-console-api/get-cors-allowed-origin /docs/APIs-and-SDKs/Web-Console-API/cors-allowed-origin-get/ 302 +/docs/web-console-api/get-environment /docs/APIs-and-SDKs/Web-Console-API/environment-get/ 302 +/docs/web-console-api/get-experiment /docs/APIs-and-SDKs/Web-Console-API/experiment-get/ 302 +/docs/web-console-api/get-experiment-activity /docs/APIs-and-SDKs/Web-Console-API/experiment-activity-get/ 302 +/docs/web-console-api/get-experiment-annotation /docs/APIs-and-SDKs/Web-Console-API/experiment-annotation-get/ 302 +/docs/web-console-api/get-experiment-tag /docs/APIs-and-SDKs/Web-Console-API/experiment-tag-get/ 302 +/docs/web-console-api/get-goal /docs/APIs-and-SDKs/Web-Console-API/goal-get/ 302 +/docs/web-console-api/get-goal-tag /docs/APIs-and-SDKs/Web-Console-API/goal-tag-get/ 302 +/docs/web-console-api/get-metric /docs/APIs-and-SDKs/Web-Console-API/metric-get/ 302 +/docs/web-console-api/get-metric-tag /docs/APIs-and-SDKs/Web-Console-API/metric-tag-get/ 302 +/docs/web-console-api/get-role /docs/APIs-and-SDKs/Web-Console-API/role-get/ 302 +/docs/web-console-api/get-segment /docs/APIs-and-SDKs/Web-Console-API/segment-get/ 302 +/docs/web-console-api/get-team /docs/APIs-and-SDKs/Web-Console-API/team-get/ 302 +/docs/web-console-api/get-unit /docs/APIs-and-SDKs/Web-Console-API/unit-get/ 302 +/docs/web-console-api/get-user /docs/APIs-and-SDKs/Web-Console-API/user-get/ 302 +/docs/web-console-api/get-user-api-keys /docs/APIs-and-SDKs/Web-Console-API/user-api-keys-get/ 302 +/docs/web-console-api/get-webhook /docs/APIs-and-SDKs/Web-Console-API/webhook-get/ 302 +/docs/web-console-api/list-api-keys /docs/APIs-and-SDKs/Web-Console-API/api-keys-list/ 302 +/docs/web-console-api/list-applications /docs/APIs-and-SDKs/Web-Console-API/applications-list/ 302 +/docs/web-console-api/list-cors-allowed-origins /docs/APIs-and-SDKs/Web-Console-API/cors-allowed-origins-list/ 302 +/docs/web-console-api/list-environments /docs/APIs-and-SDKs/Web-Console-API/environments-list/ 302 +/docs/web-console-api/list-experiment-annotations /docs/APIs-and-SDKs/Web-Console-API/experiment-annotations-list/ 302 +/docs/web-console-api/list-experiment-tags /docs/APIs-and-SDKs/Web-Console-API/experiment-tags-list/ 302 +/docs/web-console-api/list-experiments /docs/APIs-and-SDKs/Web-Console-API/experiments-list/ 302 +/docs/web-console-api/list-goal-tags /docs/APIs-and-SDKs/Web-Console-API/goal-tags-list/ 302 +/docs/web-console-api/list-goals /docs/APIs-and-SDKs/Web-Console-API/goals-list/ 302 +/docs/web-console-api/list-metric-tags /docs/APIs-and-SDKs/Web-Console-API/metric-tags-list/ 302 +/docs/web-console-api/list-metrics /docs/APIs-and-SDKs/Web-Console-API/metrics-list/ 302 +/docs/web-console-api/list-permission-categories /docs/APIs-and-SDKs/Web-Console-API/permission-categories-list/ 302 +/docs/web-console-api/list-permissions /docs/APIs-and-SDKs/Web-Console-API/permissions-list/ 302 +/docs/web-console-api/list-roles /docs/APIs-and-SDKs/Web-Console-API/roles-list/ 302 +/docs/web-console-api/list-segments /docs/APIs-and-SDKs/Web-Console-API/segments-list/ 302 +/docs/web-console-api/list-teams /docs/APIs-and-SDKs/Web-Console-API/teams-list/ 302 +/docs/web-console-api/list-units /docs/APIs-and-SDKs/Web-Console-API/units-list/ 302 +/docs/web-console-api/list-users /docs/APIs-and-SDKs/Web-Console-API/users-list/ 302 +/docs/web-console-api/list-webhook-events /docs/APIs-and-SDKs/Web-Console-API/webhook-events-list/ 302 +/docs/web-console-api/list-webhooks /docs/APIs-and-SDKs/Web-Console-API/webhooks-list/ 302 +# Base path redirects (splats don't match bare paths) +/docs/web-console-api /docs/APIs-and-SDKs/Web-Console-API/ 302 +/docs/Web-Console-API /docs/APIs-and-SDKs/Web-Console-API/ 302 + +# General splat rule (catches all other paths that don't need transformation) +/docs/web-console-api/* /docs/APIs-and-SDKs/Web-Console-API/:splat 302 +/docs/Web-Console-API/* /docs/APIs-and-SDKs/Web-Console-API/:splat 302 + +# ============================================================================= # Web Console - Configuration +# ============================================================================= /docs/web-console-docs/settings /docs/web-console-docs/Configuration/settings/ 302 +# ============================================================================= # Web Console - Users, Teams & Permissions +# ============================================================================= /docs/web-console-docs/creating-and-managing-teams /docs/web-console-docs/Users-teams-Permissions/Teams/ 302 +/docs/web-console-docs/managing-teams /docs/web-console-docs/Users-teams-Permissions/Teams/ 302 /docs/web-console-docs/ownership-and-permissions /docs/web-console-docs/Users-teams-Permissions/ownership-and-permissions/ 302 +# ============================================================================= # Web Console - Experiments +# ============================================================================= /docs/web-console-docs/Aborting-experiments /docs/web-console-docs/experiments/Aborting-experiments/ 302 /docs/web-console-docs/Experiment-health-checks /docs/web-console-docs/experiments/Experiment-health-checks/ 302 /docs/web-console-docs/Experiment-reports /docs/web-console-docs/experiments/Experiment-reports/ 302 @@ -38,9 +132,29 @@ /docs/web-console-docs/setting-up-a-gst-experiment /docs/web-console-docs/experiments/setting-up-a-gst-experiment/ 302 /docs/web-console-docs/templates /docs/web-console-docs/experiments/templates/ 302 +# Old pages that no longer exist - redirect to overview +/docs/web-console-docs/dashboard /docs/web-console-docs/overview/ 302 +/docs/web-console-docs/tutorial /docs/web-console-docs/overview/ 302 +/docs/web-console-docs/product-docs /docs/web-console-docs/overview/ 302 + +# Types of analysis +/docs/web-console-docs/types-of-analysis /docs/web-console-docs/experiments/overview/ 302 +/docs/web-console-docs/type-of-analysis /docs/web-console-docs/experiments/overview/#analysis-methods 302 + +# ============================================================================= # Web Console - Feature Flags +# ============================================================================= /docs/web-console-docs/creating-a-feature /docs/web-console-docs/feature-flags/creating-a-feature/ 302 -# Wildcards and special cases +# ============================================================================= +# Web Console - Goals and Metrics +# ============================================================================= /docs/web-console-docs/understanding-experimentation-metrics/* /docs/web-console-docs/goals-and-metrics/metrics/overview/ 302 -/docs/web-console-docs/type-of-analysis /docs/web-console-docs/experiments/overview/#analysis-methods 302 +/docs/web-console-docs/understanding-experimentation-metrics /docs/web-console-docs/goals-and-metrics/metrics/overview/ 302 +/docs/web-console-docs/Understanding-experimentation-metrics /docs/web-console-docs/goals-and-metrics/metrics/overview/ 302 +/docs/web-console-docs/goals-and-metrics/Understanding-experimentation-metrics /docs/web-console-docs/goals-and-metrics/metrics/overview/ 302 + +# ============================================================================= +# APIs-and-SDKs overview rename +# ============================================================================= +/docs/APIs-and-SDKs/apis-and-sdks /docs/APIs-and-SDKs/overview/ 302 diff --git a/test-all-urls.js b/test-all-urls.js index 8579aea7..c37e3c0f 100755 --- a/test-all-urls.js +++ b/test-all-urls.js @@ -19,9 +19,10 @@ * 2. Converts them to URL paths * 3. Tests that each page loads successfully (200 OK) * 4. Tests ALL old→new redirects work correctly + * 5. Throttles requests (200ms delay) to avoid rate limiting * - * Last Updated: 2026-01-14 (commits 45eeaf3, 666c96c, 9e122f8, 99e1733) - * Total Redirects: 25 server-side + 9 anchor transforms + anchor preservation tests = 48 total + * Last Updated: 2026-01-26 (comprehensive redirect audit) + * Total Redirects: 169 server-side + 9 anchor transforms + anchor preservation tests = 192+ total */ const { chromium } = require('playwright'); @@ -34,6 +35,13 @@ const onlyFailed = args.includes('--only-failed') || args.includes('--failed-onl const BASE_URL = args.find(arg => !arg.startsWith('--')) || 'http://localhost:3000'; const DOCS_DIR = path.join(__dirname, 'docs'); +// Throttling configuration to avoid rate limiting +const THROTTLE_MS = 25; // 25ms delay between requests (40 requests/second) + +async function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + // Previously failed pages from last run (HTTP 403) const PREVIOUSLY_FAILED_PAGES = [ '/docs/platform-release-notes/2025/10', @@ -127,9 +135,9 @@ function findAllMdxFiles(dir) { return files; } -// ALL SERVER-SIDE REDIRECTS (from static/_redirects) - 25 total +// ALL SERVER-SIDE REDIRECTS (from static/_redirects) - 169 total const SERVER_REDIRECTS = [ - // SDK Documentation moves (10) + // SDK Documentation moves - PascalCase (10) { from: '/docs/SDK-Documentation/Advanced/code-as-a-variant-variable', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/code-as-a-variant-variable', type: 'server' }, { from: '/docs/SDK-Documentation/Advanced/context-attributes', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/context-attributes', type: 'server' }, { from: '/docs/SDK-Documentation/Advanced/custom-assignments', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/custom-assignments', type: 'server' }, @@ -141,14 +149,168 @@ const SERVER_REDIRECTS = [ { from: '/docs/SDK-Documentation/getting-started', to: '/docs/APIs-and-SDKs/SDK-Documentation/getting-started', type: 'server' }, { from: '/docs/SDK-Documentation', to: '/docs/APIs-and-SDKs/SDK-Documentation', type: 'server' }, - // Examples moves (1) + // SDK Documentation moves - Lowercase/Google-indexed (10) + { from: '/docs/sdk-documentation/advanced/code-as-a-variant-variable', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/code-as-a-variant-variable', type: 'server' }, + { from: '/docs/sdk-documentation/advanced/context-attributes', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/context-attributes', type: 'server' }, + { from: '/docs/sdk-documentation/advanced/custom-assignments', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/custom-assignments', type: 'server' }, + { from: '/docs/sdk-documentation/advanced/finalize', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/finalize', type: 'server' }, + { from: '/docs/sdk-documentation/advanced/publish', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/publish', type: 'server' }, + { from: '/docs/sdk-documentation/advanced/tracking-goals', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/tracking-goals', type: 'server' }, + { from: '/docs/sdk-documentation/advanced/using-custom-fields-in-your-code', to: '/docs/APIs-and-SDKs/SDK-Documentation/Advanced/using-custom-fields-in-your-code', type: 'server' }, + { from: '/docs/sdk-documentation/basic-usage', to: '/docs/APIs-and-SDKs/SDK-Documentation/basic-usage', type: 'server' }, + { from: '/docs/sdk-documentation/getting-started', to: '/docs/APIs-and-SDKs/SDK-Documentation/getting-started', type: 'server' }, + { from: '/docs/sdk-documentation', to: '/docs/APIs-and-SDKs/SDK-Documentation', type: 'server' }, + + // Old root-level getting-started (1) + { from: '/docs/getting-started', to: '/docs/APIs-and-SDKs/SDK-Documentation/getting-started', type: 'server' }, + + // Examples moves (2) { from: '/docs/Examples/Slack-Integration', to: '/docs/APIs-and-SDKs/Web-Console-API/Examples/Slack-Integration', type: 'server' }, + { from: '/docs/examples/slack-integration', to: '/docs/APIs-and-SDKs/Web-Console-API/Examples/Slack-Integration', type: 'server' }, + + // Onboarding/SSO moves (12) + { from: '/docs/onboarding/google%20saml%20setup', to: '/docs/Third-party-integrations/SSO/Google%20SAML%20Setup', type: 'server' }, + { from: '/docs/onboarding/azure%20saml%20setup', to: '/docs/Third-party-integrations/SSO/Azure%20SAML%20Setup', type: 'server' }, + { from: '/docs/onboarding/okta%20saml%20setup', to: '/docs/Third-party-integrations/SSO/Okta%20SAML%20Setup', type: 'server' }, + { from: '/docs/onboarding/google-saml-setup', to: '/docs/Third-party-integrations/SSO/Google%20SAML%20Setup', type: 'server' }, + { from: '/docs/onboarding/azure-saml-setup', to: '/docs/Third-party-integrations/SSO/Azure%20SAML%20Setup', type: 'server' }, + { from: '/docs/onboarding/okta-saml-setup', to: '/docs/Third-party-integrations/SSO/Okta%20SAML%20Setup', type: 'server' }, + { from: '/docs/Onboarding/Google%20SAML%20Setup', to: '/docs/Third-party-integrations/SSO/Google%20SAML%20Setup', type: 'server' }, + { from: '/docs/Onboarding/Azure%20SAML%20Setup', to: '/docs/Third-party-integrations/SSO/Azure%20SAML%20Setup', type: 'server' }, + { from: '/docs/Onboarding/Okta%20SAML%20Setup', to: '/docs/Third-party-integrations/SSO/Okta%20SAML%20Setup', type: 'server' }, + { from: '/docs/web-console-docs/SSO/Google%20SAML%20Setup', to: '/docs/Third-party-integrations/SSO/Google%20SAML%20Setup', type: 'server' }, + { from: '/docs/web-console-docs/SSO/Azure%20SAML%20Setup', to: '/docs/Third-party-integrations/SSO/Azure%20SAML%20Setup', type: 'server' }, + { from: '/docs/web-console-docs/SSO/Okta%20SAML%20Setup', to: '/docs/Third-party-integrations/SSO/Okta%20SAML%20Setup', type: 'server' }, + + // Third-party integrations lowercase (3) + { from: '/docs/third-party-integrations/zuko-integration', to: '/docs/Third-party-integrations/Zuko-Integration', type: 'server' }, + { from: '/docs/third-party-integrations/slack-integration', to: '/docs/Third-party-integrations/Slack-Integration', type: 'server' }, + { from: '/docs/third-party-integrations/segment-integration', to: '/docs/Third-party-integrations/Segment-Integration', type: 'server' }, + + // Old API paths (6) + { from: '/docs/API/collector-health-check', to: '/docs/APIs-and-SDKs/SDK-API/collector-health-check', type: 'server' }, + { from: '/docs/API/context-create', to: '/docs/APIs-and-SDKs/SDK-API/context-create', type: 'server' }, + { from: '/docs/API/context-get', to: '/docs/APIs-and-SDKs/SDK-API/context-get', type: 'server' }, + { from: '/docs/API/context-publish', to: '/docs/APIs-and-SDKs/SDK-API/context-publish', type: 'server' }, + { from: '/docs/API/context-publish-batch', to: '/docs/APIs-and-SDKs/SDK-API/context-publish-batch', type: 'server' }, + { from: '/docs/API/experiment-get', to: '/docs/APIs-and-SDKs/SDK-API/experiment-get', type: 'server' }, + + // Web Console API - current naming (49) + { from: '/docs/web-console-api/absmartly-web-console-api', to: '/docs/APIs-and-SDKs/Web-Console-API/absmartly-web-console-api', type: 'server' }, + { from: '/docs/web-console-api/api-key-get', to: '/docs/APIs-and-SDKs/Web-Console-API/api-key-get', type: 'server' }, + { from: '/docs/web-console-api/api-keys-list', to: '/docs/APIs-and-SDKs/Web-Console-API/api-keys-list', type: 'server' }, + { from: '/docs/web-console-api/application-get', to: '/docs/APIs-and-SDKs/Web-Console-API/application-get', type: 'server' }, + { from: '/docs/web-console-api/applications-list', to: '/docs/APIs-and-SDKs/Web-Console-API/applications-list', type: 'server' }, + { from: '/docs/web-console-api/cors-allowed-origin-get', to: '/docs/APIs-and-SDKs/Web-Console-API/cors-allowed-origin-get', type: 'server' }, + { from: '/docs/web-console-api/cors-allowed-origins-list', to: '/docs/APIs-and-SDKs/Web-Console-API/cors-allowed-origins-list', type: 'server' }, + { from: '/docs/web-console-api/environment-get', to: '/docs/APIs-and-SDKs/Web-Console-API/environment-get', type: 'server' }, + { from: '/docs/web-console-api/environments-list', to: '/docs/APIs-and-SDKs/Web-Console-API/environments-list', type: 'server' }, + { from: '/docs/web-console-api/experiment-activity-get', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-activity-get', type: 'server' }, + { from: '/docs/web-console-api/experiment-annotation-get', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-annotation-get', type: 'server' }, + { from: '/docs/web-console-api/experiment-annotations-list', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-annotations-list', type: 'server' }, + { from: '/docs/web-console-api/experiment-archive', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-archive', type: 'server' }, + { from: '/docs/web-console-api/experiment-comment-create', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-comment-create', type: 'server' }, + { from: '/docs/web-console-api/experiment-comment-reply-create', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-comment-reply-create', type: 'server' }, + { from: '/docs/web-console-api/experiment-full-on', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-full-on', type: 'server' }, + { from: '/docs/web-console-api/experiment-get', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-get', type: 'server' }, + { from: '/docs/web-console-api/experiment-main-metrics-data', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-main-metrics-data', type: 'server' }, + { from: '/docs/web-console-api/experiment-main-metrics-history-data', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-main-metrics-history-data', type: 'server' }, + { from: '/docs/web-console-api/experiment-participants-history-data', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-participants-history-data', type: 'server' }, + { from: '/docs/web-console-api/experiment-start', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-start', type: 'server' }, + { from: '/docs/web-console-api/experiment-stop', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-stop', type: 'server' }, + { from: '/docs/web-console-api/experiment-tag-get', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-tag-get', type: 'server' }, + { from: '/docs/web-console-api/experiment-tags-list', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-tags-list', type: 'server' }, + { from: '/docs/web-console-api/experiments-list', to: '/docs/APIs-and-SDKs/Web-Console-API/experiments-list', type: 'server' }, + { from: '/docs/web-console-api/goal-get', to: '/docs/APIs-and-SDKs/Web-Console-API/goal-get', type: 'server' }, + { from: '/docs/web-console-api/goal-tag-get', to: '/docs/APIs-and-SDKs/Web-Console-API/goal-tag-get', type: 'server' }, + { from: '/docs/web-console-api/goal-tags-list', to: '/docs/APIs-and-SDKs/Web-Console-API/goal-tags-list', type: 'server' }, + { from: '/docs/web-console-api/goals-list', to: '/docs/APIs-and-SDKs/Web-Console-API/goals-list', type: 'server' }, + { from: '/docs/web-console-api/metric-get', to: '/docs/APIs-and-SDKs/Web-Console-API/metric-get', type: 'server' }, + { from: '/docs/web-console-api/metric-tag-get', to: '/docs/APIs-and-SDKs/Web-Console-API/metric-tag-get', type: 'server' }, + { from: '/docs/web-console-api/metric-tags-list', to: '/docs/APIs-and-SDKs/Web-Console-API/metric-tags-list', type: 'server' }, + { from: '/docs/web-console-api/metrics-list', to: '/docs/APIs-and-SDKs/Web-Console-API/metrics-list', type: 'server' }, + { from: '/docs/web-console-api/permission-categories-list', to: '/docs/APIs-and-SDKs/Web-Console-API/permission-categories-list', type: 'server' }, + { from: '/docs/web-console-api/permissions-list', to: '/docs/APIs-and-SDKs/Web-Console-API/permissions-list', type: 'server' }, + { from: '/docs/web-console-api/role-get', to: '/docs/APIs-and-SDKs/Web-Console-API/role-get', type: 'server' }, + { from: '/docs/web-console-api/roles-list', to: '/docs/APIs-and-SDKs/Web-Console-API/roles-list', type: 'server' }, + { from: '/docs/web-console-api/segment-get', to: '/docs/APIs-and-SDKs/Web-Console-API/segment-get', type: 'server' }, + { from: '/docs/web-console-api/segments-list', to: '/docs/APIs-and-SDKs/Web-Console-API/segments-list', type: 'server' }, + { from: '/docs/web-console-api/team-get', to: '/docs/APIs-and-SDKs/Web-Console-API/team-get', type: 'server' }, + { from: '/docs/web-console-api/teams-list', to: '/docs/APIs-and-SDKs/Web-Console-API/teams-list', type: 'server' }, + { from: '/docs/web-console-api/unit-get', to: '/docs/APIs-and-SDKs/Web-Console-API/unit-get', type: 'server' }, + { from: '/docs/web-console-api/units-list', to: '/docs/APIs-and-SDKs/Web-Console-API/units-list', type: 'server' }, + { from: '/docs/web-console-api/user-api-keys-get', to: '/docs/APIs-and-SDKs/Web-Console-API/user-api-keys-get', type: 'server' }, + { from: '/docs/web-console-api/user-get', to: '/docs/APIs-and-SDKs/Web-Console-API/user-get', type: 'server' }, + { from: '/docs/web-console-api/users-list', to: '/docs/APIs-and-SDKs/Web-Console-API/users-list', type: 'server' }, + { from: '/docs/web-console-api/webhook-events-list', to: '/docs/APIs-and-SDKs/Web-Console-API/webhook-events-list', type: 'server' }, + { from: '/docs/web-console-api/webhook-get', to: '/docs/APIs-and-SDKs/Web-Console-API/webhook-get', type: 'server' }, + { from: '/docs/web-console-api/webhooks-list', to: '/docs/APIs-and-SDKs/Web-Console-API/webhooks-list', type: 'server' }, + + // Web Console API - old naming convention get-*/list-* (39) + { from: '/docs/web-console-api/get-api-key', to: '/docs/APIs-and-SDKs/Web-Console-API/api-key-get', type: 'server' }, + { from: '/docs/web-console-api/get-application', to: '/docs/APIs-and-SDKs/Web-Console-API/application-get', type: 'server' }, + { from: '/docs/web-console-api/get-cors-allowed-origin', to: '/docs/APIs-and-SDKs/Web-Console-API/cors-allowed-origin-get', type: 'server' }, + { from: '/docs/web-console-api/get-environment', to: '/docs/APIs-and-SDKs/Web-Console-API/environment-get', type: 'server' }, + { from: '/docs/web-console-api/get-experiment', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-get', type: 'server' }, + { from: '/docs/web-console-api/get-experiment-activity', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-activity-get', type: 'server' }, + { from: '/docs/web-console-api/get-experiment-annotation', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-annotation-get', type: 'server' }, + { from: '/docs/web-console-api/get-experiment-tag', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-tag-get', type: 'server' }, + { from: '/docs/web-console-api/get-goal', to: '/docs/APIs-and-SDKs/Web-Console-API/goal-get', type: 'server' }, + { from: '/docs/web-console-api/get-goal-tag', to: '/docs/APIs-and-SDKs/Web-Console-API/goal-tag-get', type: 'server' }, + { from: '/docs/web-console-api/get-metric', to: '/docs/APIs-and-SDKs/Web-Console-API/metric-get', type: 'server' }, + { from: '/docs/web-console-api/get-metric-tag', to: '/docs/APIs-and-SDKs/Web-Console-API/metric-tag-get', type: 'server' }, + { from: '/docs/web-console-api/get-role', to: '/docs/APIs-and-SDKs/Web-Console-API/role-get', type: 'server' }, + { from: '/docs/web-console-api/get-segment', to: '/docs/APIs-and-SDKs/Web-Console-API/segment-get', type: 'server' }, + { from: '/docs/web-console-api/get-team', to: '/docs/APIs-and-SDKs/Web-Console-API/team-get', type: 'server' }, + { from: '/docs/web-console-api/get-unit', to: '/docs/APIs-and-SDKs/Web-Console-API/unit-get', type: 'server' }, + { from: '/docs/web-console-api/get-user', to: '/docs/APIs-and-SDKs/Web-Console-API/user-get', type: 'server' }, + { from: '/docs/web-console-api/get-user-api-keys', to: '/docs/APIs-and-SDKs/Web-Console-API/user-api-keys-get', type: 'server' }, + { from: '/docs/web-console-api/get-webhook', to: '/docs/APIs-and-SDKs/Web-Console-API/webhook-get', type: 'server' }, + { from: '/docs/web-console-api/list-api-keys', to: '/docs/APIs-and-SDKs/Web-Console-API/api-keys-list', type: 'server' }, + { from: '/docs/web-console-api/list-applications', to: '/docs/APIs-and-SDKs/Web-Console-API/applications-list', type: 'server' }, + { from: '/docs/web-console-api/list-cors-allowed-origins', to: '/docs/APIs-and-SDKs/Web-Console-API/cors-allowed-origins-list', type: 'server' }, + { from: '/docs/web-console-api/list-environments', to: '/docs/APIs-and-SDKs/Web-Console-API/environments-list', type: 'server' }, + { from: '/docs/web-console-api/list-experiment-annotations', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-annotations-list', type: 'server' }, + { from: '/docs/web-console-api/list-experiment-tags', to: '/docs/APIs-and-SDKs/Web-Console-API/experiment-tags-list', type: 'server' }, + { from: '/docs/web-console-api/list-experiments', to: '/docs/APIs-and-SDKs/Web-Console-API/experiments-list', type: 'server' }, + { from: '/docs/web-console-api/list-goal-tags', to: '/docs/APIs-and-SDKs/Web-Console-API/goal-tags-list', type: 'server' }, + { from: '/docs/web-console-api/list-goals', to: '/docs/APIs-and-SDKs/Web-Console-API/goals-list', type: 'server' }, + { from: '/docs/web-console-api/list-metric-tags', to: '/docs/APIs-and-SDKs/Web-Console-API/metric-tags-list', type: 'server' }, + { from: '/docs/web-console-api/list-metrics', to: '/docs/APIs-and-SDKs/Web-Console-API/metrics-list', type: 'server' }, + { from: '/docs/web-console-api/list-permission-categories', to: '/docs/APIs-and-SDKs/Web-Console-API/permission-categories-list', type: 'server' }, + { from: '/docs/web-console-api/list-permissions', to: '/docs/APIs-and-SDKs/Web-Console-API/permissions-list', type: 'server' }, + { from: '/docs/web-console-api/list-roles', to: '/docs/APIs-and-SDKs/Web-Console-API/roles-list', type: 'server' }, + { from: '/docs/web-console-api/list-segments', to: '/docs/APIs-and-SDKs/Web-Console-API/segments-list', type: 'server' }, + { from: '/docs/web-console-api/list-teams', to: '/docs/APIs-and-SDKs/Web-Console-API/teams-list', type: 'server' }, + { from: '/docs/web-console-api/list-units', to: '/docs/APIs-and-SDKs/Web-Console-API/units-list', type: 'server' }, + { from: '/docs/web-console-api/list-users', to: '/docs/APIs-and-SDKs/Web-Console-API/users-list', type: 'server' }, + { from: '/docs/web-console-api/list-webhook-events', to: '/docs/APIs-and-SDKs/Web-Console-API/webhook-events-list', type: 'server' }, + { from: '/docs/web-console-api/list-webhooks', to: '/docs/APIs-and-SDKs/Web-Console-API/webhooks-list', type: 'server' }, + + // SDK API - lowercase (7) + { from: '/docs/sdk-api/absmartly-collector-api', to: '/docs/APIs-and-SDKs/SDK-API/absmartly-collector-api', type: 'server' }, + { from: '/docs/sdk-api/collector-health-check', to: '/docs/APIs-and-SDKs/SDK-API/collector-health-check', type: 'server' }, + { from: '/docs/sdk-api/context-create', to: '/docs/APIs-and-SDKs/SDK-API/context-create', type: 'server' }, + { from: '/docs/sdk-api/context-get', to: '/docs/APIs-and-SDKs/SDK-API/context-get', type: 'server' }, + { from: '/docs/sdk-api/context-publish', to: '/docs/APIs-and-SDKs/SDK-API/context-publish', type: 'server' }, + { from: '/docs/sdk-api/context-publish-batch', to: '/docs/APIs-and-SDKs/SDK-API/context-publish-batch', type: 'server' }, + { from: '/docs/sdk-api/experiment-get', to: '/docs/APIs-and-SDKs/SDK-API/experiment-get', type: 'server' }, + + // SDK API - PascalCase (7) + { from: '/docs/SDK-API/absmartly-collector-api', to: '/docs/APIs-and-SDKs/SDK-API/absmartly-collector-api', type: 'server' }, + { from: '/docs/SDK-API/collector-health-check', to: '/docs/APIs-and-SDKs/SDK-API/collector-health-check', type: 'server' }, + { from: '/docs/SDK-API/context-create', to: '/docs/APIs-and-SDKs/SDK-API/context-create', type: 'server' }, + { from: '/docs/SDK-API/context-get', to: '/docs/APIs-and-SDKs/SDK-API/context-get', type: 'server' }, + { from: '/docs/SDK-API/context-publish', to: '/docs/APIs-and-SDKs/SDK-API/context-publish', type: 'server' }, + { from: '/docs/SDK-API/context-publish-batch', to: '/docs/APIs-and-SDKs/SDK-API/context-publish-batch', type: 'server' }, + { from: '/docs/SDK-API/experiment-get', to: '/docs/APIs-and-SDKs/SDK-API/experiment-get', type: 'server' }, // Web Console - Configuration (1) { from: '/docs/web-console-docs/settings', to: '/docs/web-console-docs/Configuration/settings', type: 'server' }, - // Web Console - Users, Teams & Permissions (2) + // Web Console - Users, Teams & Permissions (3) { from: '/docs/web-console-docs/creating-and-managing-teams', to: '/docs/web-console-docs/Users-teams-Permissions/Teams', type: 'server' }, + { from: '/docs/web-console-docs/managing-teams', to: '/docs/web-console-docs/Users-teams-Permissions/Teams', type: 'server' }, { from: '/docs/web-console-docs/ownership-and-permissions', to: '/docs/web-console-docs/Users-teams-Permissions/ownership-and-permissions', type: 'server' }, // Web Console - Experiments (8) @@ -161,30 +323,82 @@ const SERVER_REDIRECTS = [ { from: '/docs/web-console-docs/setting-up-a-gst-experiment', to: '/docs/web-console-docs/experiments/setting-up-a-gst-experiment', type: 'server' }, { from: '/docs/web-console-docs/templates', to: '/docs/web-console-docs/experiments/templates', type: 'server' }, + // Old pages that no longer exist (3) + { from: '/docs/web-console-docs/dashboard', to: '/docs/web-console-docs/overview', type: 'server' }, + { from: '/docs/web-console-docs/tutorial', to: '/docs/web-console-docs/overview', type: 'server' }, + { from: '/docs/web-console-docs/product-docs', to: '/docs/web-console-docs/overview', type: 'server' }, + + // Types of analysis (1) + { from: '/docs/web-console-docs/types-of-analysis', to: '/docs/web-console-docs/experiments/overview', type: 'server' }, + // Web Console - Feature Flags (1) { from: '/docs/web-console-docs/creating-a-feature', to: '/docs/web-console-docs/feature-flags/creating-a-feature', type: 'server' }, - // Wildcards and special cases (2) + // Understanding experimentation metrics variations (4) { from: '/docs/web-console-docs/understanding-experimentation-metrics/test', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview', type: 'server-wildcard' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview', type: 'server' }, + { from: '/docs/web-console-docs/Understanding-experimentation-metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview', type: 'server' }, + { from: '/docs/web-console-docs/goals-and-metrics/Understanding-experimentation-metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview', type: 'server' }, + + // Type of analysis with anchor (1) { from: '/docs/web-console-docs/type-of-analysis', to: '/docs/web-console-docs/experiments/overview#analysis-methods', type: 'server-with-anchor' }, + + // APIs-and-SDKs overview rename (1) + { from: '/docs/APIs-and-SDKs/apis-and-sdks', to: '/docs/APIs-and-SDKs/overview', type: 'server' }, ]; -// CLIENT-SIDE ANCHOR REDIRECTS (from anchorRedirects.ts) - 9 total that transform +// CLIENT-SIDE ANCHOR REDIRECTS (from anchorRedirects.ts) - transforms and cross-page const ANCHOR_REDIRECTS = [ - // Creating an Experiment - same-page anchor transforms (2) + // Creating an Experiment - same-page anchor transforms { from: '/docs/web-console-docs/creating-an-experiment#application', to: '/docs/web-console-docs/experiments/creating-an-experiment#applications', type: 'js-transform' }, { from: '/docs/web-console-docs/creating-an-experiment#targeting-audiences', to: '/docs/web-console-docs/experiments/creating-an-experiment#audiences', type: 'js-transform' }, - // Creating an Experiment - cross-page redirects (3) + // Creating an Experiment - cross-page redirects { from: '/docs/web-console-docs/creating-an-experiment#error-control', to: '/docs/web-console-docs/experiments/setting-up-a-gst-experiment#error-control', type: 'js-cross-page' }, { from: '/docs/web-console-docs/creating-an-experiment#sample-size-calculation', to: '/docs/web-console-docs/experiments/setting-up-a-gst-experiment#what-is-the-experiment-duration-based-on', type: 'js-cross-page' }, { from: '/docs/web-console-docs/creating-an-experiment#type-of-analysis', to: '/docs/web-console-docs/experiments/overview#analysis-methods', type: 'js-cross-page' }, - // Creating a Feature - same-page anchor transforms (4) + // Creating a Feature - same-page anchor transforms { from: '/docs/web-console-docs/creating-a-feature#feature-name', to: '/docs/web-console-docs/feature-flags/creating-a-feature#basics', type: 'js-transform' }, { from: '/docs/web-console-docs/creating-a-feature#tracking-unit', to: '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', type: 'js-transform' }, { from: '/docs/web-console-docs/creating-a-feature#application', to: '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', type: 'js-transform' }, { from: '/docs/web-console-docs/creating-a-feature#targeting-audiences', to: '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', type: 'js-transform' }, + + // Templates - anchor rename + { from: '/docs/web-console-docs/templates#introduction', to: '/docs/web-console-docs/experiments/templates#overview', type: 'js-transform' }, + + // Managing teams - anchor renames + { from: '/docs/web-console-docs/managing-teams#creating-a-team', to: '/docs/web-console-docs/Users-teams-Permissions/Teams#create-a-team', type: 'js-transform' }, + { from: '/docs/web-console-docs/managing-teams#viewing-the-company-hierarchy', to: '/docs/web-console-docs/Users-teams-Permissions/Teams#viewing-the-team-hierarchy', type: 'js-transform' }, + { from: '/docs/web-console-docs/creating-and-managing-teams#creating-a-team', to: '/docs/web-console-docs/Users-teams-Permissions/Teams#create-a-team', type: 'js-transform' }, + { from: '/docs/web-console-docs/creating-and-managing-teams#viewing-the-company-hierarchy', to: '/docs/web-console-docs/Users-teams-Permissions/Teams#viewing-the-team-hierarchy', type: 'js-transform' }, + + // Settings - sections moved to separate pages + { from: '/docs/web-console-docs/settings#applications', to: '/docs/web-console-docs/Configuration/Applications', type: 'js-cross-page' }, + { from: '/docs/web-console-docs/settings#units', to: '/docs/web-console-docs/Configuration/Units', type: 'js-cross-page' }, + { from: '/docs/web-console-docs/settings#goals', to: '/docs/web-console-docs/goals-and-metrics/goals/overview', type: 'js-cross-page' }, + { from: '/docs/web-console-docs/settings#metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview', type: 'js-cross-page' }, + { from: '/docs/web-console-docs/settings#teams', to: '/docs/web-console-docs/Users-teams-Permissions/Teams', type: 'js-cross-page' }, + + // Types-of-analysis - anchor renames + { from: '/docs/web-console-docs/types-of-analysis#fixed-horizon-testing', to: '/docs/web-console-docs/experiments/overview#fixed-horizon', type: 'js-transform' }, + { from: '/docs/web-console-docs/types-of-analysis#group-sequential-testing', to: '/docs/web-console-docs/experiments/overview#group-sequential', type: 'js-transform' }, + { from: '/docs/web-console-docs/types-of-analysis#which-analysis-type-should-i-choose-for-my-experiment', to: '/docs/web-console-docs/experiments/overview#how-to-choose', type: 'js-transform' }, + + // Understanding-experimentation-metrics - sections consolidated + { from: '/docs/web-console-docs/understanding-experimentation-metrics#primary-metric', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#secondary-metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#guardrail-metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#exploratory-metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#business', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#purpose', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#behavioural', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#purpose', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#operational', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#purpose', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#binomial', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#data-structure', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#continuous', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#data-structure', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#short-term', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#time-horizon', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#long-term', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#time-horizon', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#proxy', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#functionality', type: 'js-transform' }, + { from: '/docs/web-console-docs/understanding-experimentation-metrics#composite', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#functionality', type: 'js-transform' }, ]; // BROWSER ANCHOR PRESERVATION TESTS - verify unchanged anchors are preserved @@ -203,10 +417,39 @@ const ANCHOR_PRESERVATION_TESTS = [ // NEW PATH ANCHOR TRANSFORMS - verify JS works on new paths const NEW_PATH_ANCHOR_TESTS = [ + // Creating an Experiment - new path anchor transforms { from: '/docs/web-console-docs/experiments/creating-an-experiment#application', to: '/docs/web-console-docs/experiments/creating-an-experiment#applications', type: 'js-new-path' }, { from: '/docs/web-console-docs/experiments/creating-an-experiment#targeting-audiences', to: '/docs/web-console-docs/experiments/creating-an-experiment#audiences', type: 'js-new-path' }, { from: '/docs/web-console-docs/experiments/creating-an-experiment#error-control', to: '/docs/web-console-docs/experiments/setting-up-a-gst-experiment#error-control', type: 'js-new-path' }, + + // Creating a Feature - new path anchor transforms { from: '/docs/web-console-docs/feature-flags/creating-a-feature#feature-name', to: '/docs/web-console-docs/feature-flags/creating-a-feature#basics', type: 'js-new-path' }, + { from: '/docs/web-console-docs/feature-flags/creating-a-feature#tracking-unit', to: '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', type: 'js-new-path' }, + { from: '/docs/web-console-docs/feature-flags/creating-a-feature#application', to: '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', type: 'js-new-path' }, + { from: '/docs/web-console-docs/feature-flags/creating-a-feature#targeting-audiences', to: '/docs/web-console-docs/feature-flags/creating-a-feature#audiences', type: 'js-new-path' }, + + // Templates - new path anchor transform + { from: '/docs/web-console-docs/experiments/templates#introduction', to: '/docs/web-console-docs/experiments/templates#overview', type: 'js-new-path' }, + + // Teams - new path anchor transforms + { from: '/docs/web-console-docs/Users-teams-Permissions/Teams#creating-a-team', to: '/docs/web-console-docs/Users-teams-Permissions/Teams#create-a-team', type: 'js-new-path' }, + { from: '/docs/web-console-docs/Users-teams-Permissions/Teams#viewing-the-company-hierarchy', to: '/docs/web-console-docs/Users-teams-Permissions/Teams#viewing-the-team-hierarchy', type: 'js-new-path' }, + + // Settings - new path cross-page anchors + { from: '/docs/web-console-docs/Configuration/settings#applications', to: '/docs/web-console-docs/Configuration/Applications', type: 'js-new-path' }, + { from: '/docs/web-console-docs/Configuration/settings#units', to: '/docs/web-console-docs/Configuration/Units', type: 'js-new-path' }, + { from: '/docs/web-console-docs/Configuration/settings#goals', to: '/docs/web-console-docs/goals-and-metrics/goals/overview', type: 'js-new-path' }, + { from: '/docs/web-console-docs/Configuration/settings#metrics', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview', type: 'js-new-path' }, + { from: '/docs/web-console-docs/Configuration/settings#teams', to: '/docs/web-console-docs/Users-teams-Permissions/Teams', type: 'js-new-path' }, + + // Experiments overview - new path anchor transforms + { from: '/docs/web-console-docs/experiments/overview#fixed-horizon-testing', to: '/docs/web-console-docs/experiments/overview#fixed-horizon', type: 'js-new-path' }, + { from: '/docs/web-console-docs/experiments/overview#group-sequential-testing', to: '/docs/web-console-docs/experiments/overview#group-sequential', type: 'js-new-path' }, + { from: '/docs/web-console-docs/experiments/overview#which-analysis-type-should-i-choose-for-my-experiment', to: '/docs/web-console-docs/experiments/overview#how-to-choose', type: 'js-new-path' }, + + // Metrics overview - new path anchor transforms + { from: '/docs/web-console-docs/goals-and-metrics/metrics/overview#primary-metric', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#role', type: 'js-new-path' }, + { from: '/docs/web-console-docs/goals-and-metrics/metrics/overview#binomial', to: '/docs/web-console-docs/goals-and-metrics/metrics/overview#data-structure', type: 'js-new-path' }, ]; // Combine all redirect tests @@ -253,8 +496,9 @@ async function checkRedirect(page, fromPath, expectedToPath) { const fullFromUrl = `${BASE_URL}${fromPath}`; try { - await page.goto(fullFromUrl, { - waitUntil: 'networkidle', + // Navigate and follow all redirects + const response = await page.goto(fullFromUrl, { + waitUntil: 'domcontentloaded', timeout: 15000 }); @@ -264,9 +508,11 @@ async function checkRedirect(page, fromPath, expectedToPath) { const finalUrl = page.url(); const finalPath = finalUrl.replace(BASE_URL, ''); + // Normalize for comparison (case-insensitive) const normalizedFinal = normalizeUrl(finalPath); const normalizedExpected = normalizeUrl(expectedToPath); + // Case-insensitive comparison (Netlify may lowercase URLs) const match = normalizedFinal === normalizedExpected; return { @@ -274,7 +520,8 @@ async function checkRedirect(page, fromPath, expectedToPath) { match, fromPath, expectedPath: expectedToPath, - finalPath + finalPath, + statusCode: response.status() }; } catch (error) { return { @@ -335,7 +582,8 @@ async function testAllUrls() { let pagesFailed = 0; const failedPages = []; - for (const urlPath of pageUrls) { + for (let i = 0; i < pageUrls.length; i++) { + const urlPath = pageUrls[i]; const result = await checkPageLoads(page, urlPath); if (result.success) { @@ -345,20 +593,24 @@ async function testAllUrls() { pagesFailed++; failedPages.push(result); process.stdout.write('❌'); + // Show failed page immediately + console.log(` ${urlPath} (${result.error})`); } // New line every 50 tests for readability if ((pagesOk + pagesFailed) % 50 === 0) { process.stdout.write(` [${pagesOk + pagesFailed}/${pageUrls.length}]\n`); } + + // Throttle to avoid rate limiting + await sleep(THROTTLE_MS); } console.log(`\n[${pagesOk + pagesFailed}/${pageUrls.length}]\n`); console.log(`Pages tested: ${pageUrls.length}`); console.log(`✅ Passed: ${pagesOk}`); - console.log(`❌ Failed: ${pagesFailed}`); - if (pagesFailed > 0) { + console.log(`❌ Failed: ${pagesFailed}`); console.log(''); console.log('❌ Failed pages:'); failedPages.forEach(p => { @@ -392,28 +644,29 @@ async function testAllUrls() { if (result.match) { redirectsOk++; redirectsByType[redirectTest.type].passed++; - process.stdout.write('✅'); + console.log(`✅ ${redirectTest.from} → ${redirectTest.to}`); } else { redirectsFailed++; redirectsByType[redirectTest.type].failed++; failedRedirects.push(result); - process.stdout.write('❌'); + console.log(`❌ ${redirectTest.from} → ${redirectTest.to}`); + console.log(` Expected: ${redirectTest.to}, Got: ${result.finalPath || 'error'}`); + if (result.error) { + console.log(` Error: ${result.error}`); + } } redirectsByType[redirectTest.type].tests.push(result); - // New line every 25 tests - if ((redirectsOk + redirectsFailed) % 25 === 0) { - process.stdout.write(` [${redirectsOk + redirectsFailed}/${ALL_REDIRECT_TESTS.length}]\n`); - } + // Throttle to avoid rate limiting + await sleep(THROTTLE_MS); } console.log(`\n[${redirectsOk + redirectsFailed}/${ALL_REDIRECT_TESTS.length}]\n`); console.log(`Redirects tested: ${ALL_REDIRECT_TESTS.length}`); console.log(`✅ Passed: ${redirectsOk}`); - console.log(`❌ Failed: ${redirectsFailed}`); - if (redirectsFailed > 0) { + console.log(`❌ Failed: ${redirectsFailed}`); console.log(''); console.log('❌ Failed redirects:'); failedRedirects.forEach(r => { @@ -432,7 +685,8 @@ async function testAllUrls() { if (stats.passed + stats.failed === 0) continue; const total = stats.passed + stats.failed; const status = stats.failed === 0 ? '✅' : '❌'; - console.log(` ${status} ${type}: ${stats.passed}/${total} passed`); + const failedText = stats.failed > 0 ? `, ${stats.failed} failed` : ''; + console.log(` ${status} ${type}: ${stats.passed}/${total} passed${failedText}`); } await browser.close(); @@ -445,15 +699,21 @@ async function testAllUrls() { console.log(''); console.log(`Total documentation pages: ${pageUrls.length}`); console.log(` ✅ Working: ${pagesOk}`); - console.log(` ❌ Broken: ${pagesFailed}`); + if (pagesFailed > 0) { + console.log(` ❌ Broken: ${pagesFailed}`); + } console.log(''); console.log(`Total redirects: ${ALL_REDIRECT_TESTS.length}`); console.log(` ✅ Working: ${redirectsOk}`); - console.log(` ❌ Broken: ${redirectsFailed}`); + if (redirectsFailed > 0) { + console.log(` ❌ Broken: ${redirectsFailed}`); + } console.log(''); console.log(`GRAND TOTAL: ${pageUrls.length + ALL_REDIRECT_TESTS.length} URLs tested`); console.log(` ✅ Passed: ${pagesOk + redirectsOk}`); - console.log(` ❌ Failed: ${pagesFailed + redirectsFailed}`); + if (pagesFailed + redirectsFailed > 0) { + console.log(` ❌ Failed: ${pagesFailed + redirectsFailed}`); + } console.log(''); const totalFailed = pagesFailed + redirectsFailed;