From a41065adeb2da2a58777d5462fedf0b92433ef1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20D=C4=85browski?= Date: Mon, 21 Oct 2024 20:56:36 +0000 Subject: [PATCH] Deploy website - based on 791f842d04541354075f3b1d09586e62c66724f0 --- 404.html | 4 ++-- .../{929714a5.8a34703a.js => 929714a5.0f61aba6.js} | 2 +- .../{ecbe7f2c.f5c6d415.js => ecbe7f2c.873d88e4.js} | 2 +- assets/js/{main.dfd8699e.js => main.c826b051.js} | 4 ++-- ...e.js.LICENSE.txt => main.c826b051.js.LICENSE.txt} | 0 ...ime~main.cafd5221.js => runtime~main.bf34d40c.js} | 2 +- docs/ampscript/ampscript-style-guide/index.html | 4 ++-- docs/category/-ampscript-snippets/index.html | 4 ++-- docs/category/-js-snippets/index.html | 4 ++-- .../category/-mc-personalization-snippets/index.html | 4 ++-- docs/category/-serverside-code/index.html | 4 ++-- docs/category/-sql-snippets/index.html | 4 ++-- docs/category/-ssjs-snippets/index.html | 4 ++-- docs/category/ampscript/index.html | 4 ++-- docs/category/javascript/index.html | 4 ++-- docs/category/mc-personalization/index.html | 4 ++-- docs/category/sfmc-config/index.html | 4 ++-- docs/category/sfmc-sql/index.html | 4 ++-- docs/category/sfmc-webinars/index.html | 4 ++-- docs/category/ssjs/index.html | 4 ++-- docs/config/sfmc-appexchange-solutions/index.html | 4 ++-- docs/config/sfmc-behavioral-triggers/index.html | 4 ++-- docs/config/sfmc-code-resource/index.html | 4 ++-- docs/config/sfmc-contact-deletion/index.html | 4 ++-- docs/config/sfmc-enhanced-send-log/index.html | 4 ++-- docs/config/sfmc-features-on-demand/index.html | 4 ++-- docs/config/sfmc-licence-limits/index.html | 4 ++-- docs/config/sfmc-mcc-integration-patterns/index.html | 4 ++-- .../config/sfmc-mobile-connect-data-views/index.html | 4 ++-- docs/config/sfmc-system-data-views/index.html | 4 ++-- docs/index.html | 4 ++-- .../mcp-catalog-architecture/index.html | 4 ++-- .../mcp-open-time-email/index.html | 4 ++-- .../mcp-serverside-code-basics/index.html | 4 ++-- .../mcp-serverside-code-context/index.html | 12 ++++++------ .../mcp-serverside-code-properties/index.html | 4 ++-- .../mcp-catalog-etl-metadata-viewer/index.html | 4 ++-- docs/js/js-dom/index.html | 4 ++-- docs/js/js-if-and-switch/index.html | 4 ++-- docs/js/js-loops/index.html | 4 ++-- docs/js/snippets/engage-with-countdown/index.html | 6 +++--- .../export-import-document-sfmc-roles/index.html | 4 ++-- docs/js/snippets/tailor-with-data/index.html | 4 ++-- docs/sql/sfmc-sql-aggregate-functions/index.html | 4 ++-- docs/sql/sfmc-sql-basics/index.html | 4 ++-- docs/sql/sfmc-sql-case/index.html | 4 ++-- docs/sql/sfmc-sql-conversion-functions/index.html | 4 ++-- docs/sql/sfmc-sql-date-functions/index.html | 4 ++-- docs/sql/sfmc-sql-from/index.html | 4 ++-- docs/sql/sfmc-sql-join/index.html | 4 ++-- docs/sql/sfmc-sql-like/index.html | 4 ++-- docs/sql/sfmc-sql-null-functions/index.html | 4 ++-- docs/sql/sfmc-sql-numeric-functions/index.html | 4 ++-- docs/sql/sfmc-sql-select/index.html | 4 ++-- docs/sql/sfmc-sql-string-functions/index.html | 4 ++-- docs/sql/sfmc-sql-style-guide/index.html | 8 ++++---- docs/sql/sfmc-sql-where/index.html | 4 ++-- .../sfmc-sql-debugging-email-sends/index.html | 4 ++-- .../sfmc-sql-debugging-value-length/index.html | 4 ++-- docs/ssjs/debugging-ssjs/index.html | 4 ++-- docs/ssjs/snippets/ampscript-in-ssjs/index.html | 4 ++-- docs/ssjs/snippets/sfmc-cloud-page-apps/index.html | 4 ++-- .../ssjs-mobileconnect-phone-change/index.html | 4 ++-- docs/ssjs/snippets/ssjs-script-template/index.html | 4 ++-- docs/ssjs/ssjs-if-and-switch/index.html | 4 ++-- docs/ssjs/ssjs-loops/index.html | 4 ++-- docs/ssjs/ssjs-style-guide/index.html | 4 ++-- docs/ssjs/ssjs-vs-ampscript-performance/index.html | 4 ++-- docs/tags/amp-script/index.html | 4 ++-- docs/tags/analytics/index.html | 4 ++-- docs/tags/api/index.html | 4 ++-- docs/tags/app-exchange/index.html | 4 ++-- docs/tags/app/index.html | 4 ++-- docs/tags/automation/index.html | 4 ++-- docs/tags/behavioral-triggers/index.html | 4 ++-- docs/tags/best-practice/index.html | 4 ++-- docs/tags/cloud-page/index.html | 4 ++-- docs/tags/configuration/index.html | 4 ++-- docs/tags/crm/index.html | 4 ++-- docs/tags/data-extensions/index.html | 4 ++-- docs/tags/data-management/index.html | 4 ++-- docs/tags/debugging/index.html | 4 ++-- docs/tags/deliverability/index.html | 4 ++-- docs/tags/einstein/index.html | 4 ++-- docs/tags/eloqua/index.html | 4 ++-- docs/tags/email/index.html | 4 ++-- docs/tags/index.html | 4 ++-- docs/tags/integration/index.html | 4 ++-- docs/tags/interaction-studio/index.html | 4 ++-- docs/tags/java-script/index.html | 4 ++-- docs/tags/journey/index.html | 4 ++-- docs/tags/marketing-cloud-personalization/index.html | 4 ++-- docs/tags/marketing-cloud/index.html | 4 ++-- docs/tags/performance/index.html | 4 ++-- docs/tags/personalisation/index.html | 4 ++-- docs/tags/setup/index.html | 4 ++-- docs/tags/sms/index.html | 4 ++-- docs/tags/snippet/index.html | 4 ++-- docs/tags/sql/index.html | 4 ++-- docs/tags/ssjs/index.html | 4 ++-- docs/tags/style-guide/index.html | 4 ++-- docs/tags/type-script/index.html | 4 ++-- docs/tags/users/index.html | 4 ++-- docs/tags/webinar/index.html | 4 ++-- .../sfmc-webinar-account-architecture/index.html | 4 ++-- .../index.html | 4 ++-- .../webinars/sfmc-webinar-cloud-page-apps/index.html | 4 ++-- .../index.html | 4 ++-- docs/zen-of-sfmc/index.html | 4 ++-- index.html | 4 ++-- search/index.html | 4 ++-- sites/category/faq/index.html | 4 ++-- sites/category/ideas/index.html | 4 ++-- .../how-to-get-sf-certification-vouchers/index.html | 4 ++-- .../how-to-get-sfmc-hands-on-experience/index.html | 4 ++-- sites/ideas/marketing-cloud-ideas/index.html | 4 ++-- sites/ideas/mc-personalization-ideas/index.html | 4 ++-- sites/licence/index.html | 4 ++-- sites/my-toolset/index.html | 4 ++-- sites/newsletter/index.html | 4 ++-- sites/privacy/index.html | 4 ++-- sites/tags/best-practice/index.html | 4 ++-- sites/tags/faq/index.html | 4 ++-- sites/tags/index.html | 4 ++-- sites/tags/interaction-studio/index.html | 4 ++-- .../tags/marketing-cloud-personalization/index.html | 4 ++-- sites/tags/marketing-cloud/index.html | 4 ++-- sites/tags/personalization/index.html | 4 ++-- 128 files changed, 258 insertions(+), 258 deletions(-) rename assets/js/{929714a5.8a34703a.js => 929714a5.0f61aba6.js} (55%) rename assets/js/{ecbe7f2c.f5c6d415.js => ecbe7f2c.873d88e4.js} (96%) rename assets/js/{main.dfd8699e.js => main.c826b051.js} (99%) rename assets/js/{main.dfd8699e.js.LICENSE.txt => main.c826b051.js.LICENSE.txt} (100%) rename assets/js/{runtime~main.cafd5221.js => runtime~main.bf34d40c.js} (98%) diff --git a/404.html b/404.html index 4bd9c8284..5814d589c 100644 --- a/404.html +++ b/404.html @@ -10,8 +10,8 @@ - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

diff --git a/assets/js/929714a5.8a34703a.js b/assets/js/929714a5.0f61aba6.js similarity index 55% rename from assets/js/929714a5.8a34703a.js rename to assets/js/929714a5.0f61aba6.js index 90e4d3f08..3d8a1982c 100644 --- a/assets/js/929714a5.8a34703a.js +++ b/assets/js/929714a5.0f61aba6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmd=self.webpackChunkmd||[]).push([[3823],{4519:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var s=n(4848),i=n(8453),r=n(6748);const o={id:"mcp-serverside-code-context",title:"MCP Serverside Code Context",sidebar_label:"Serverside Code Context",description:"Context is king. Also when writing MCP Template Serverside Code.",image:"img/og/og-image-mcp-serverside-code-context.png",tags:["Marketing Cloud","Marketing Cloud Personalization","Interaction Studio","Personalisation","TypeScript"]},a=void 0,c={id:"interaction-studio/mcp-serverside-code-context",title:"MCP Serverside Code Context",description:"Context is king. Also when writing MCP Template Serverside Code.",source:"@site/docs/interaction-studio/mcp-serverside-code-context.mdx",sourceDirName:"interaction-studio",slug:"/interaction-studio/mcp-serverside-code-context",permalink:"/docs/interaction-studio/mcp-serverside-code-context",draft:!1,unlisted:!1,editUrl:"https://github.com/MateuszDabrowski/mateuszdabrowski.pl/edit/master/docs/interaction-studio/mcp-serverside-code-context.mdx",tags:[{inline:!0,label:"Marketing Cloud",permalink:"/docs/tags/marketing-cloud"},{inline:!0,label:"Marketing Cloud Personalization",permalink:"/docs/tags/marketing-cloud-personalization"},{inline:!0,label:"Interaction Studio",permalink:"/docs/tags/interaction-studio"},{inline:!0,label:"Personalisation",permalink:"/docs/tags/personalisation"},{inline:!0,label:"TypeScript",permalink:"/docs/tags/type-script"}],version:"current",lastUpdatedBy:"Mateusz D\u0105browski",lastUpdatedAt:1722957473e3,frontMatter:{id:"mcp-serverside-code-context",title:"MCP Serverside Code Context",sidebar_label:"Serverside Code Context",description:"Context is king. Also when writing MCP Template Serverside Code.",image:"img/og/og-image-mcp-serverside-code-context.png",tags:["Marketing Cloud","Marketing Cloud Personalization","Interaction Studio","Personalisation","TypeScript"]},sidebar:"docs",previous:{title:"Serverside Code Properties",permalink:"/docs/interaction-studio/mcp-serverside-code-properties"},next:{title:"\u203a MC Personalization Snippets",permalink:"/docs/category/-mc-personalization-snippets"}},d={},l=[{value:"campaignId & experienceId",id:"campaignid--experienceid",level:2},{value:"userGroup",id:"usergroup",level:2},{value:"beaconVersion",id:"beaconversion",level:2},{value:"event",id:"event",level:2},{value:"event methods",id:"event-methods",level:3},{value:"context.event.ipAddress()",id:"contexteventipaddress",level:4},{value:"context.event.itemId()",id:"contexteventitemid",level:4},{value:"context.event.itemType()",id:"contexteventitemtype",level:4},{value:"event.fields",id:"eventfields",level:3},{value:"context.event.fields.pageType",id:"contexteventfieldspagetype",level:4},{value:"context.event.fields.action",id:"contexteventfieldsaction",level:4},{value:"context.event.fields.url",id:"contexteventfieldsurl",level:4},{value:"context.event.fields.customAttribute",id:"contexteventfieldscustomattribute",level:4},{value:"contentZone",id:"contentzone",level:2},{value:"trigger",id:"trigger",level:2},{value:"locale",id:"locale",level:2},{value:"services",id:"services",level:2},{value:"services.catalog",id:"servicescatalog",level:3},{value:"context.services.catalog.findItem()",id:"contextservicescatalogfinditem",level:4},{value:"context.services.catalog.findItems()",id:"contextservicescatalogfinditems",level:4},{value:"context.services.catalog.findClosestItems()",id:"contextservicescatalogfindclosestitems",level:4},{value:"context.services.catalog.dimensionFilter()",id:"contextservicescatalogdimensionfilter",level:4},{value:"services.recommendations",id:"servicesrecommendations",level:3},{value:"context.services.recommendations.recommend()",id:"contextservicesrecommendationsrecommend",level:4},{value:"context.services.recommendations.recommendIdsOnly()",id:"contextservicesrecommendationsrecommendidsonly",level:4},{value:"context.services.recommendations.smartSearch()",id:"contextservicesrecommendationssmartsearch",level:4},{value:"context.services.recommendations.smartSort()",id:"contextservicesrecommendationssmartsort",level:4},{value:"services.smartTrends",id:"servicessmarttrends",level:3},{value:"services.surveys",id:"servicessurveys",level:3},{value:"services.decisions",id:"servicesdecisions",level:3},{value:"services.corvus",id:"servicescorvus",level:3},{value:"services.promotionCatalog",id:"servicespromotioncatalog",level:3},{value:"user",id:"user",level:2},{value:"user methods",id:"user-methods",level:3},{value:"context.user.actionCount()",id:"contextuseractioncount",level:4},{value:"context.user.actionCountPerItem()",id:"contextuseractioncountperitem",level:4},{value:"context.user.getDimensionActivity()",id:"contextusergetdimensionactivity",level:4},{value:"context.user.getDimensionActivityByDay()",id:"contextusergetdimensionactivitybyday",level:4},{value:"context.user.getEmailSendHistory()",id:"contextusergetemailsendhistory",level:4},{value:"context.user.getLatestOrderByStatus()",id:"contextusergetlatestorderbystatus",level:4},{value:"context.user.getSegmentJoinDate()",id:"contextusergetsegmentjoindate",level:4},{value:"context.user.itemStatTotal()",id:"contextuseritemstattotal",level:4},{value:"context.user.itemStatTotalPerItem()",id:"contextuseritemstattotalperitem",level:4},{value:"context.user.pageViewCount()",id:"contextuserpageviewcount",level:4},{value:"context.user.visitCount()",id:"contextuservisitcount",level:4},{value:"context.user.visitDurationMilis()",id:"contextuservisitdurationmilis",level:4},{value:"user.attributes",id:"userattributes",level:3},{value:"user.profileObjects",id:"userprofileobjects",level:3},{value:"user.visits",id:"uservisits",level:3},{value:"user.orderHistory",id:"userorderhistory",level:3},{value:"user.location",id:"userlocation",level:3},{value:"user.currentCart",id:"usercurrentcart",level:3},{value:"user.segmentMembership",id:"usersegmentmembership",level:3},{value:"accountId & datasetId",id:"accountid--datasetid",level:2},{value:"configuration",id:"configuration",level:2}];function h(e){const t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.U,{content:"Context is king. Also when coding MCP Campaign Templates. Read about all its undocumented tricks."}),"\n",(0,s.jsxs)(t.p,{children:["Marketing Cloud Personalization offers flexible campaign template creation tooling with multiple ",(0,s.jsx)(t.a,{href:"/docs/interaction-studio/mcp-serverside-code-properties",children:"properties"})," and imports that help you fulfil business needs while providing a pleasant user experience for the marketer. There is also one more\u2014undocumented\u2014feature that can change your template from good to outstanding: the CampaignComponentContext object."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["In this article, I'm covering the main ",(0,s.jsx)(t.code,{children:"CampaignComponentContext"})," object that is passed as a ",(0,s.jsx)(t.code,{children:"context"})," argument to the ",(0,s.jsxs)(t.a,{href:"/docs/interaction-studio/mcp-serverside-code-basics#writing-serverside-code",children:[(0,s.jsx)(t.code,{children:"run"})," block"]})," in the Serverside Code of every campaign template."]}),(0,s.jsxs)(t.p,{children:["Some other contexts (like ",(0,s.jsx)(t.code,{children:"GearLifecycleContext"})," passed to search methods) have different structures and are out of the scope of this article."]})]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"CampaignComponentContext"})," object is available in the Serverside Code of the Web, Serverside and Triggered Campaign Templates and provides extensive details about triggering event, user and delivered experience."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context object"',children:'{\n "campaignId": string,\n "experienceId": string,\n "userGroup": string,\n "beaconVersion": number,\n "event": Object,\n "contentZone": string,\n "trigger": Object,\n "locale": string,\n "services": Object,\n "user": Object,\n "accountId": string,\n "datasetId": string,\n "configuration": Object\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"It's straightforward to use once you know what's in there. For example, you can pull product ID stored with Sitemap in a User Attribute and leverage it to pull complete data about that product for personalisation:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2-3} title="Leverage context in the run method of your Serverside Code"',children:" run(context: CampaignComponentContext) {\n const lastAddedToCartProductId = context.user.attributes?.lastAddedToCartProduct?.value;\n const lastAddedToCartProductDetails = context.services.catalog.findItem('Product', lastAddedToCartProductId);\n return { lastATCDetails: lastAddedToCartProductDetails };\n }\n"})}),"\n",(0,s.jsxs)(t.p,{children:["And that's just a basic usage. The key to unlocking the power of a context object is knowing what is stored there and how to use it. So let's dive in, property by property (hint: the fun part starts at ",(0,s.jsx)(t.a,{href:"#event",children:(0,s.jsx)(t.code,{children:"event"})}),")."]}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsx)(t.p,{children:"This article is a work in progress. I'm continually extending details about various parts of the context object as I use it in real life."})}),"\n",(0,s.jsx)(t.h2,{id:"campaignid--experienceid",children:"campaignId & experienceId"}),"\n",(0,s.jsxs)(t.p,{children:["The first two string properties of the context object are ",(0,s.jsx)(t.code,{children:"campaignId"})," and ",(0,s.jsx)(t.code,{children:"experienceId"}),", and their purpose is very straightforward. They provide the five-character, case-sensitive, alphanumerical IDs for the campaign and experience selected for a user (for example, ",(0,s.jsx)(t.code,{children:"vALdQ"})," for Campaign ID and ",(0,s.jsx)(t.code,{children:"f3WpK"})," for Experience ID)."]}),"\n",(0,s.jsxs)(t.p,{children:["Both those values are passed by default from serverside to clientside and handlebars (as ",(0,s.jsx)(t.code,{children:"campaign"})," and ",(0,s.jsx)(t.code,{children:"experience"})," accordingly), so there is not much added value in the two unless you want to append those values as query strings to the links for tracking purposes."]}),"\n",(0,s.jsx)(t.p,{children:"However, for Web Campaigns, you can do it easily within the handlebars tab, and for Serverside and Triggered Campaigns, you can do it on the receiving system side."}),"\n",(0,s.jsx)(t.h2,{id:"usergroup",children:"userGroup"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"userGroup"})," string property should tell you the group assigned to the user. Well, it should. In practice, you will see there one of the two values: ",(0,s.jsx)(t.code,{children:"Test"})," for users that got an A/B Test or Rule-Based experience and ",(0,s.jsx)(t.code,{children:"testUserGroup"})," for those that are in the Control group (or in the Template preview pane within MCP UI)."]}),"\n",(0,s.jsxs)(t.p,{children:["However, you will see better values in the out-of-the-box serverside payload ",(0,s.jsx)(t.code,{children:"userGroup"})," property that correctly shows values like ",(0,s.jsx)(t.code,{children:"Test"}),", ",(0,s.jsx)(t.code,{children:"Default"}),", and ",(0,s.jsx)(t.code,{children:"Control"})," and only displays ",(0,s.jsx)(t.code,{children:"testUserGroup"})," during preview."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["The control group creates more problems for the context, as it keeps displaying the payload preview version of it. So you will also see only the placeholder values for ",(0,s.jsxs)(t.a,{href:"#campaignid--experienceid",children:[(0,s.jsx)(t.code,{children:"campaignId"})," and ",(0,s.jsx)(t.code,{children:"experienceId"})]}),", ",(0,s.jsx)(t.a,{href:"#beaconversion",children:(0,s.jsx)(t.code,{children:"beaconVersion"})})," and skip other datapoints like ",(0,s.jsx)(t.a,{href:"#event",children:(0,s.jsx)(t.code,{children:"event.fields"})}),"."]}),(0,s.jsxs)(t.p,{children:["In short, don't use ",(0,s.jsx)(t.code,{children:"context"})," for custom payload dedicated to control group users."]})]}),"\n",(0,s.jsx)(t.h2,{id:"beaconversion",children:"beaconVersion"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"beaconVersion"})," number property will display the current Web SDK version (e.g., ",(0,s.jsx)(t.code,{children:"16"})," at the time of writing) or ",(0,s.jsx)(t.code,{children:"0"})," for the preview/control group. Not really useful."]}),"\n",(0,s.jsx)(t.h2,{id:"event",children:"event"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"event"})," object property is where the magic of the ",(0,s.jsx)(t.code,{children:"context"})," object starts. It stores information about the event that triggered the campaign - the data you can see when you leverage the ",(0,s.jsx)(t.code,{children:".setLoggingLevel('debug')"})," method in your Sitemap."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"context.event"})," object won't work correctly in the Template Preview sidebar, as there is no valid event in that mode. Use an active campaign directly on the website to preview the actual output during development. Make sure you use the campaign targeting to limit execution just to you."]}),(0,s.jsxs)(t.p,{children:["In Template Preview, you will only be able to use ",(0,s.jsx)(t.a,{href:"#eventfields",children:(0,s.jsx)(t.code,{children:"context.event.fields.item"})})," - a single property with a stringified object containing details of the Item selected in the top right Simulate section):"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:'"{\\"type\\":\\"ITEM_TYPE\\",\\"_id\\":{\\"label\\":\\"ITEM_LABEL\\",\\"value\\":\\"ITEM_ID\\"}}"\n'})}),(0,s.jsxs)(t.p,{children:["My ",(0,s.jsx)(t.a,{href:"/docs/interaction-studio/snippets/mcp-catalog-etl-metadata-viewer",children:"MCP Catalog ETL Metadata Viewer"})," provides an example of its usage."]})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.event object"',children:'{\n "time": datetime,\n "fields": Object,\n "ipAddress": (): string,\n "itemId": (): string,\n "itemType": (): string\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["While the ",(0,s.jsx)(t.code,{children:"context.event.time"})," is not that useful (unless you want to make some time-dependent changes to the campaign payload), the three available methods are much more practical."]}),"\n",(0,s.jsx)(t.h3,{id:"event-methods",children:"event methods"}),"\n",(0,s.jsx)(t.h4,{id:"contexteventipaddress",children:"context.event.ipAddress()"}),"\n",(0,s.jsx)(t.p,{children:"Returns an IP address of the user visiting your website. You might use it to blocklist specific IP ranges (internal or competitors) from seeing your campaigns. It's not a clean solution (as the campaign needs to be executed to get this far), but this might be your best bet, as there is no MCP-level IP blocklist. Of course, a much better solution would be to build such logic on the website side to block IPs already on the Web SDK import step conditionally, but that might not always be possible."}),"\n",(0,s.jsx)(t.h4,{id:"contexteventitemid",children:"context.event.itemId()"}),"\n",(0,s.jsxs)(t.p,{children:["Returns the ID of the Catalog Item the user viewed in the event. It pairs perfectly with the following method: ",(0,s.jsx)(t.code,{children:"context.event.itemType()"}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contexteventitemtype",children:"context.event.itemType()"}),"\n",(0,s.jsxs)(t.p,{children:["Returns the Catalog of the Item viewed (f.e. ",(0,s.jsx)(t.code,{children:"'Product'"})," for Product View)."]}),"\n",(0,s.jsxs)(t.p,{children:["The pair of ",(0,s.jsx)(t.code,{children:"itemId"})," and ",(0,s.jsx)(t.code,{children:"itemType"})," is handy, as those two details are precisely what MCP requires for a ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog.findItem()"})})," call that lets you get complete details about the currently displayed item. It enables use cases where you want to change the campaign payload based on displayed item attributes, related catalog objects, or other information on the item details. For example, access to ",(0,s.jsx)(t.a,{href:"#locale",children:"localized item data"}),"."]}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsxs)(t.p,{children:["Event is not only an excellent data point that you can access through ",(0,s.jsx)(t.code,{children:"context"}),". It is also the basis for the anchor in Einstein Recipes. You can leverage it (in a filthy way) to create fake anchors and deploy recommendations for products related to the one currently viewed."]})}),"\n",(0,s.jsxs)(t.p,{children:["On top of the above, ",(0,s.jsx)(t.code,{children:"context.event"})," also contains the ",(0,s.jsx)(t.code,{children:"context.event.fields"})," subobject, capturing even more details about the triggering event."]}),"\n",(0,s.jsx)(t.h3,{id:"eventfields",children:"event.fields"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.event.fields object"',children:'{\n ".anonId": string,\n ".bv": string,\n ".pv": boolean,\n ".scv": number,\n ".skipProcessing": boolean,\n "action": string,\n "channel": string,\n "clientIp": string,\n "contentZones": string[],\n "pageType": string,\n "url": string,\n "urlref": string,\n "userAgent": string,\n "_anon": boolean,\n "_debug": boolean,\n "customAttribute1": any,\n "customAttribute2": any\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.event.fields"})," subobject groups multiple data points, many of which are very technical and not really useful for us. But some can open exciting use cases - let's dive in."]}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldspagetype",children:"context.event.fields.pageType"}),"\n",(0,s.jsx)(t.p,{children:'Returns the name of the currently viewed page type as configured in the Sitemap (e.g., "Home"). This is useful when you want to adapt the campaign\'s serverside payload based on page type when the content zone is shared across many sites.'}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldsaction",children:"context.event.fields.action"}),"\n",(0,s.jsxs)(t.p,{children:["Returns the name of the currently pushed action as configured in the Sitemap (f.e. ",(0,s.jsx)(t.code,{children:"'Viewed Home'"}),"). It shines for custom action names that can drive different campaign experiences - despite being triggered on the same page type."]}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldsurl",children:"context.event.fields.url"}),"\n",(0,s.jsx)(t.p,{children:"Returns the URL where the event originated. The cool part is that it contains the hash and query strings, so you can drive use cases using those elements (f.e. change the experience based on the query string values you set in the email campaign using SFMC data)."}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldscustomattribute",children:"context.event.fields.customAttribute"}),"\n",(0,s.jsxs)(t.p,{children:["Apart from those always-there properties, you will also see custom attributes you passed along with the event. For example, if in the Sitemap you are passing SFMC Contact Key along with the event: ",(0,s.jsx)(t.code,{children:"actionEvent.user.attributes.sfmcContactKey = queryParameters.get('sk');"})," you will have ",(0,s.jsx)(t.code,{children:"context.event.fields.sfmcContactKey"})," property available with that value. This is huge - it enables us to build campaigns leveraging real-time data. Use cases? Sure! Create an ",(0,s.jsx)(t.code,{children:"hasAddedInsurance"})," attribute filled out by the Add to Cart event to determine whether you want to promote a cross-sell. Add the ",(0,s.jsx)(t.code,{children:"hasMetFreeDeliveryThershold"})," boolean field to conditionally trigger recommendations of products that will help the customer get over the line of free delivery. The sky is the limit with those."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["If you need some data only for the specific event purpose and don't want to store it in an attribute (be it due to limits or because Sitemap cannot remove the attribute value later), you can still use the ",(0,s.jsx)(t.code,{children:"actionEvent.user.attributes.customAttribute = 'value'"})," approach to pass that information. It won't be stored on the user attribute (if there isn't one matching the name) but will still be available on the Event Stream and in the ",(0,s.jsx)(t.code,{children:"context"})," object as ",(0,s.jsx)(t.code,{children:"context.event.fields.customAttribute"}),". Works also for pushing custom events:"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'{5} title="Pushing custom event with a custom attribute that does not exist as a user attribute"',children:"Evergage.sendEvent({\n action: 'Custom Event',\n user: {\n attributes: {\n customAttribute: 'value', // You can make up any property name you want\n },\n },\n source: {\n contentZones: [{ name: 'virtual_for_global_control' }],\n }\n})\n"})})]}),"\n",(0,s.jsx)(t.h2,{id:"contentzone",children:"contentZone"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"contentZone"})," string property returns the Content Zone selected for the Campaign. It might be helpful if your campaign supports multiple content zones and you want to alter some payload elements based on the one selected (f.e. change the number of returned recommendations):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2} title="Leverage context.contentZone to change the serverside payload"',children:"// Limit the number of recommendations to the first four for smaller placements\nif (['search_see-more', 'listing_see-more'].includes(context.contentZone)) {\n recommendations = recommendations.slice(0,4);\n}\n"})}),"\n",(0,s.jsx)(t.h2,{id:"trigger",children:"trigger"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"trigger"})," object property is filled only for the Triggered Campaign Templates."]}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h2,{id:"locale",children:"locale"}),"\n",(0,s.jsxs)(t.p,{children:["If you have switched on Locale support in your Marketing Cloud Personalization, the ",(0,s.jsx)(t.code,{children:"locale"})," string will return a five-character long combination of ISO language code and ISO country code (",(0,s.jsx)(t.code,{children:"language_COUNTRY"}),", for example: ",(0,s.jsx)(t.code,{children:"en_US"})," for American English)."]}),"\n",(0,s.jsx)(t.p,{children:"You can use it to return the campaign content based on the most recent user locale (be it based on manually entered variations in the Campaign configuration or by pulling directly from the localized Catalog):"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{7} title="Leverage context.locale to pull localized product details"',children:"const recommendedIds = recommendIdsOnly(context, recipeConfig);\n// Return localized recommendations with key data points needed for the campaign\nlet localisedRecommendations = context.services.catalog\n .findItems('Product', recommendedIds)\n .map(product => product.toFlatJSON(\n ['id', 'name,' 'imageUrl', 'url', 'price'],\n context.locale || ''\n ))\n"})}),"\n",(0,s.jsx)(t.h2,{id:"services",children:"services"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.services"})," is the most potent part of the ",(0,s.jsx)(t.code,{children:"context"})," object - packed to the brim with methods that give you access to Marketing Cloud Personalization data or let you create new recommendations."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services object"',children:'{\n "catalog": Object,\n "recommendations": Object,\n "smartTrends": Object,\n "surveys": Object,\n "decisions": Object,\n "corvus": Object,\n "promotionCatalog": Object\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"It's a nested object, so let's go through it property by property to discuss each group of methods."}),"\n",(0,s.jsx)(t.h3,{id:"servicescatalog",children:"services.catalog"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"services.catalog"})," object contains a set of lookup methods that help you find Items in your Marketing Cloud Personalization Catalogs. It opens a wide range of use cases for using related Items for cross-sell and up-sell purposes."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.catalog object"',children:'{\n "dimensionFilter": (dimension: string): ItemFilter,\n "findClosestItems": (request: ClosestItemsRequest): Item[],\n "findItem": (type: string, id: string): Item,\n "findItems": (type: string, ids: string[]): Item[] || (type: ItemFilter, ids: ItemSort): Item[] || (type: ItemFilter): Item[]\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Most of those methods return an Item object - the content of it will differ depending on what type of item it is. By default, it will contain an ",(0,s.jsx)(t.code,{children:"id"})," string and an ",(0,s.jsx)(t.code,{children:"attributes"})," object with a ",(0,s.jsx)(t.code,{children:"name"}),", ",(0,s.jsx)(t.code,{children:"imageUrl"}),", ",(0,s.jsx)(t.code,{children:"description"}),", ",(0,s.jsx)(t.code,{children:"promotable"})," and ",(0,s.jsx)(t.code,{children:"archived"})," properties. Optionally, an Item can also have a ",(0,s.jsx)(t.code,{children:"dimensions"})," object with RCO's data and a ",(0,s.jsx)(t.code,{children:"location"})," object. Finally, some properties are related to a specific type of an Item - like ",(0,s.jsx)(t.code,{children:"categories"}),", ",(0,s.jsx)(t.code,{children:"skus"}),", ",(0,s.jsx)(t.code,{children:"modifiedTime"})," or ",(0,s.jsx)(t.code,{children:"subtitle"}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-json",metastring:'title="Example Item structure for a Product Catalog"',children:'{\n "id": "2050055",\n "location": null,\n "attributes": {\n "imageUrl": {\n "value": "https://www.northerntrailoutfitters.com/on/demandware.static/-/Sites-nto-apparel/default/dwf53f2476/images/large/2050055BEY-0.jpg"\n },\n "promotable": {\n "value": true\n },\n "price": {\n "value": 120\n },\n "inventoryCount": {\n "value": 1\n },\n "name": {\n "value": "Women\'s Hedgehog Agile NTO-tech"\n },\n "url": {\n "value": "https://www.northerntrailoutfitters.com/default/women%27s-hedgehog-agile-nto-tech-2050055BEY.html"\n },\n "archived": {\n "value": false\n },\n "customAttribute": {\n "value": "customValue"\n }\n },\n "dimensions": {\n "Color": [\n "AZT",\n "APD",\n "ANZ",\n "AO5",\n "BEY"\n ],\n "Feature": [\n "Waterproof",\n "Lightweight",\n "Breathable"\n ],\n "Gender": [\n "WOMEN"\n ]\n },\n "categories": [\n "WOMEN|FOOTWEAR|HIKING"\n ],\n "skus": {\n "2050055BEY": {\n "id": "2050055BEY"\n }\n }\n}\n'})}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogfinditem",children:"context.services.catalog.findItem()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"findItem()"})," is the most straightforward Catalog lookup method. It requires a Catalog Type (e.g., 'Product', 'Category', or your custom Catalog) and an Item ID (as a string) to return the full Item detail."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return Item details"',children:"const itemDetails = context.services.catalog.findItem('Product', '19542');\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It pairs perfectly with the ",(0,s.jsxs)(t.a,{href:"#event-methods",children:[(0,s.jsx)(t.code,{children:"context.event"})," methods"]})," if you want to get additional details of the currently viewed product (extremely useful when you are using ETL and strict catalog security for catalog data ingestion):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3} title="Return Item details dynamically"',children:"const itemType = context.event.itemType();\nconst itemId = context.event.itemId();\nconst itemDetails = context.services.catalog.findItem(itemType, itemId);\n"})}),"\n",(0,s.jsx)(t.p,{children:"This pairing lets us implement complex use cases like recommending direct cross-sells or up-sells using IDs passed to custom attributes on the product:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return cross and up-sell details dynamically"',children:"// Get details of the currently viewed item\nconst itemId = context.event.itemId();\nconst viewedItemDetails = context.services.catalog.findItem('Product', itemId);\n// Leverage those details to pull IDs of the hardcoded up-sell and cross-sell products\nconst upSellableItemId = viewedItemDetails.attributes?.upSellableItemId?.value;\nconst crossSellableItemId = viewedItemDetails.attributes?.crossSellableItemId?.value;\n// Pass those IDs to yet another findItem method to get full details and fill in the handlebars with data\nconst upSellableItemDetails = context.services.catalog.findItem('Product', upSellableItemId);\nconst crossSellableItemDetails = context.services.catalog.findItem('Product', crossSellableItemId);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["Of course, making so many ",(0,s.jsx)(t.code,{children:"findItem()"})," calls is not optimal, and MCP offers another method as a solution."]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogfinditems",children:"context.services.catalog.findItems()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"findItems()"})," method allows you to request details for multiple Items in a single call, which is cleaner and more performant. The baseline way of calling this function works just as ",(0,s.jsx)(t.a,{href:"#contextservicescatalogfinditem",children:(0,s.jsx)(t.code,{children:"findItem()"})}),", but it requires an array of IDs instead of a single ID and returns an array of Item detail objects instead of a single Item object."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return multiple Items details"',children:"const itemsDetails = context.services.catalog.findItem('Product', ['19542', '12524', '91324']);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["A neat use case for that method is pulling currently viewed Item details with ",(0,s.jsx)(t.a,{href:"#contextservicescatalogfinditem",children:(0,s.jsx)(t.code,{children:"findItem()"})})," to get values from a custom attribute containing alternative product IDs or dedicated accessories for it. Then, pass all those found product IDs into ",(0,s.jsx)(t.code,{children:"findItems()"})," to get the full detail required for a personalization showcasing those related items."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"findItems()"})," method offers more. You are not limited to just pushing an array of IDs like mentioned above - you can also pass an ItemFilter (created by ",(0,s.jsx)(t.a,{href:"#contextservicescatalogdimensionfilter",children:(0,s.jsx)(t.code,{children:"dimensionFilter()"})})," method) to get the IDs of items available in a custom (and only custom) Catalog."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2} title="Return multiple Items details"',children:"const catalogFilter = context.services.catalog.dimensionFilter('Color');\nconst itemsDetails = context.services.catalog.findItems(catalogFilter);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It can be further extended that custom-catalog-based approach by passing an ItemSort as a second argument. However, despite trying my luck with the ",(0,s.jsx)(t.code,{children:"sortByActivity"})," and ",(0,s.jsx)(t.code,{children:"sortByPublishedDate"})," properties, I haven't been able to make it work. That's too bad, as sorting by activity could have been interesting when working with custom Catalog Items."]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogfindclosestitems",children:"context.services.catalog.findClosestItems()"}),"\n",(0,s.jsxs)(t.p,{children:["If you are using location details for your Items, the ",(0,s.jsx)(t.code,{children:"findClosestItems()"})," method will work wonders for you as it allows you to get items based on the provided longitude and latitude within a defined distance:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2} title="Return multiple Items details"',children:"const closestDefinition = {itemType: 'Product', latitude: 52.23, longitude: 21.0118, maxDistance: 10, maxResults: 5};\nconst itemsDetails = context.services.catalog.findClosestItems(closestDefinition);\n"})}),"\n",(0,s.jsx)(t.p,{children:"As you can see, you need to provide an object with itemType, longitude and latitude, maxDistance (in miles) and maxResults as an argument. All fields are required. Of course, you don't have to hardcode it. There are two neat use cases around dynamically provided longitude and latitude:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["You can try to get longitude and latitude from ",(0,s.jsx)(t.a,{href:"#userlocation",children:(0,s.jsx)(t.code,{children:"context.user.location.geographicPoint"})}),". It allows you to make magic-like recommendations even for anonymous, first-time visits. However, confidence might be limited depending on the market specifics."]}),"\n",(0,s.jsxs)(t.li,{children:["You can capture user-provided location (based on the shipping details or the city they are filtering for on your website) and pass calculated long/lat to a user attribute. Then, use that user attribute as the source of data for the ",(0,s.jsx)(t.code,{children:"findClosestItems()"})," call to provide location-aware recommendations for your customers."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogdimensionfilter",children:"context.services.catalog.dimensionFilter()"}),"\n",(0,s.jsxs)(t.p,{children:["As mentioned in ",(0,s.jsx)(t.a,{href:"#contextservicescatalogfinditems",children:(0,s.jsx)(t.code,{children:"findItems()"})}),", the ",(0,s.jsx)(t.code,{children:"dimensionFilter()"})," method lets us create an ItemFilter that can be leveraged to find Items from a given custom catalog (which used to be called a Dimension, hence the method name). Just pass the Catalog name as a string there. That's it."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Create an ItemFilter for Color Catalog"',children:"const catalogFilter = context.services.catalog.dimensionFilter('Color');\n"})}),"\n",(0,s.jsx)(t.h3,{id:"servicesrecommendations",children:"services.recommendations"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"services.recommendations"})," object contains four methods related to Item recommendations. Two of them are absolutely great for delivering highly customized cross-selling use cases, while the other two don't seem to work. It's a nice mixed bag. Let's dive in."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.recommendations object"',children:'{\n "recommend": (request: RecommendationsRequest): Item[],\n "recommendIdsOnly": (request: RecommendationsRequest): Item[],\n "smartSearch": (request: SmartSearchRequest): Item[],\n "smartSort": (request: SmartSort): Item[]\n}\n'})}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationsrecommend",children:"context.services.recommendations.recommend()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"recommend()"})," method is an excellent solution for generating Item recommendations in a programmatic and highly customized way. It requires ",(0,s.jsx)(t.code,{children:"currentItemId"})," and ",(0,s.jsx)(t.code,{children:"currentItemType"})," as an anchor for the Recipe, ",(0,s.jsx)(t.code,{children:"maxResults"})," to limit the number of outcomes, ",(0,s.jsx)(t.code,{children:"recipeId"})," to apply the correct recommendation model and ",(0,s.jsx)(t.code,{children:"userId"})," to pull the correct affinity data."]}),"\n",(0,s.jsxs)(t.p,{children:["Those data points can be hard coded, pulled from marketer-filled fields or captured from other context properties like ",(0,s.jsx)(t.a,{href:"#user",children:(0,s.jsx)(t.code,{children:"context.user.id"})}),", ",(0,s.jsx)(t.a,{href:"#contexteventitemid",children:(0,s.jsx)(t.code,{children:"context.event.itemId()"})})," and ",(0,s.jsx)(t.a,{href:"#contexteventitemtype",children:(0,s.jsx)(t.code,{children:"context.event.itemType()"})})," or ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog"})})," outputs."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{9} title="Return details of items recommended from a recipe"',children:"const userId = context.user.id;\nconst recommendationsRequest = {\n currentItemId: '1017847',\n currentItemType: 'Product',\n maxResults: 12,\n recipeId: '7H5OK',\n userId: userId\n}\nconst recommendedItems = context.services.recommendations.recommend(recommendationsRequest);\n"})}),"\n",(0,s.jsx)(t.p,{children:"It's a great feature for deploying recommendations that shouldn't be changed during campaign configuration, cross-selling offerings based on the currently viewed item (using its custom attributes), or filtering items based on negative recipes."}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"recommend()"})," method works just as the ",(0,s.jsx)(t.code,{children:"recommend"})," that you can import in the template along with ",(0,s.jsx)(t.code,{children:"RecommendationsConfig"})," from the ",(0,s.jsx)(t.code,{children:"recs"})," module. The imported one is better suited for the user-friendly module that the marketer can set up according to the business needs during the campaign configuration phase. The context method is better for deploying hardcoded logic programmatically without any input from the marketer\u2014the key value being the possibility of providing a custom Item anchor that might be different from the currently viewed one."]}),(0,s.jsxs)(t.p,{children:["However, forcing a custom anchor Item is also possible with the imported ",(0,s.jsx)(t.code,{children:"recommend"})," thanks to the ",(0,s.jsx)(t.code,{children:"overrideOnPageAnchor()"})," method (requiring ",(0,s.jsx)(t.code,{children:"itemId"})," and ",(0,s.jsx)(t.code,{children:"itemType"})," string arguments) that can be deployed both along with RecommendationsConfig as well as within the ",(0,s.jsxs)(t.a,{href:"/docs/interaction-studio/mcp-serverside-code-basics#writing-serverside-code",children:[(0,s.jsx)(t.code,{children:"run"})," block"]}),":"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{9} title="Changing Item anchor for recommendation"',children:"import { RecommendationsConfig, recommend } from \"recs\";\n\nexport class customAnchorRecommendation implements CampaignTemplateComponent {\n // Renders interface for configuring the recommendation\n recsConfig: RecommendationsConfig = new RecommendationsConfig().restrictItemType(\"Product\");\n\n run(context: CampaignComponentContext) {\n // Replaces currently viewed Item anchor context with a custom one\n this.recsConfig.overrideOnPageAnchor('251422', 'Product');\n\n return {\n products: recommend(context, this.recsConfig),\n };\n }\n}\n"})})]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationsrecommendidsonly",children:"context.services.recommendations.recommendIdsOnly()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"recommendIdsOnly()"})," method works like ",(0,s.jsx)(t.a,{href:"#contextservicesrecommendationsrecommend",children:(0,s.jsx)(t.code,{children:"recommend()"})}),", but instead of returning an array of objects with Item details, it returns an array of Item IDs as strings. Just as ",(0,s.jsx)(t.code,{children:"recommendIdsOnly"})," you can import with ",(0,s.jsx)(t.code,{children:"RecommendationsConfig"})," from the ",(0,s.jsx)(t.code,{children:"recs"})," module."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{8} title="Return IDs of items recommended from a recipe"',children:"const recommendationsRequest = {\n currentItemId: '1017847',\n currentItemType: 'Product',\n maxResults: 12,\n recipeId: '7H5OK',\n userId: context.user.id\n}\nconst recommendedItemIds = context.services.recommendations.recommendIdsOnly(recommendationsRequest);\n"})}),"\n",(0,s.jsx)(t.p,{children:"It can be helpful if you only need to pass IDs to the e-commerce platform for it to render the campaign experience or when you want to filter out specific IDs returned by a recipe from another recommendation you deploy."}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationssmartsearch",children:"context.services.recommendations.smartSearch()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"smartSearch()"})," method allows you to get recommendations based on search query string and a recipe (for example, to recommend items when user interacts with a search box on the page):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{7} title="Return Items recommended using smart search"',children:'const smartSearchRequest = {\n query: "blue%20jacket",\n maxResults: 1,\n recipeId: "7H5OK",\n userId: context.user.id\n}\nconst recommendedItems = context.services.recommendations.smartSearch(smartSearchRequest);\n'})}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"query"})," parameter is looking for a match in the name (and only name), then filters found Items using the provided Recipe ID. Keep in mind that the Recipe cannot be using Ingredients requiring an Item anchor. It\u2019s best to use the Any Items ingredient and then optionally sort it using ",(0,s.jsx)(t.a,{href:"#contextservicesrecommendationssmartsort",children:(0,s.jsx)(t.code,{children:"smartSort()"})}),"."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"smartSearch()"})," can return more than 12 recommendations (it can bring back thousand - and frequently it will need to so that there pool big enough for proper ",(0,s.jsx)(t.a,{href:"#contextservicesrecommendationssmartsort",children:(0,s.jsx)(t.code,{children:"smartSort()"})})," results), but as it returns whole Item details, it can impact performance. It might be helpful to filter the outcome just to the information required for your purpose for further processing."]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return only IDs of items recommended using smart search"',children:"const recommendedItemsIds = context.services.recommendations.smartSearch(smartSearchRequest).map(item => item.id);\n"})})]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationssmartsort",children:"context.services.recommendations.smartSort()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"smartSort()"})," method requires an object with an ",(0,s.jsx)(t.code,{children:"itemIds"})," array, ",(0,s.jsx)(t.code,{children:"recipeId"}),", and ",(0,s.jsx)(t.code,{children:"userId"}),". It is a cool feature for the ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog"})})," set of functions as it can filter and order Item IDs pulled from a custom attribute or a catalog retrieve based on current user interest using a provided Recipe."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{7} title="Return items sorted using a Recipe"',children:"const itemsToBeSorted = ['1018913', '60365', '1017847', '1105'];\nconst smartSortRequest = {\n itemIds: itemsToBeSorted,\n recipeId: '7H5OK',\n userId: context.user.id\n}\nconst smartSortedItems = context.services.recommendations.smartSort(smartSortRequest);\n"})}),"\n",(0,s.jsx)(t.h3,{id:"servicessmarttrends",children:"services.smartTrends"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"smartTrends()"})," method lets you leverage the MCP Trends feature directly in the Serverside code of the Campaign. It requires a special ",(0,s.jsx)(t.code,{children:"SmartTrendsRequest"})," argument structure (",(0,s.jsx)(t.code,{children:"{itemIds: ['1018913'], itemType: \"Product\", lookbackMinutes: 9999 }"}),") and returns an array of objects with product engagement details within the provided lookback (",(0,s.jsx)(t.code,{children:"[{itemId: '1018913', visitViews: 1234, purchases: 98}]"}),")."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Return item engagement details"',children:"const smartTrendsRequest: SmartTrendsRequest = {\n itemIds: ['1018913'],\n itemType: 'Product',\n lookbackMinutes: 1656\n}\nconst smartTrendItemDetails = context.services.smartTrends.smartTrends(smartTrendsRequest);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It\u2019s a nice and more powerful alternative to the client-side code API approach based on the ",(0,s.jsx)(t.a,{href:"https://github.com/MateuszDabrowski/mcp-campaign-templates/tree/main/Global%20Templates/SalesforceInteractions/Trends",children:"Trends Global Template"}),"."]}),"\n",(0,s.jsx)(t.h3,{id:"servicessurveys",children:"services.surveys"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.surveys object"',children:'{\n "getSurey": (surveyId: string): Survey\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"servicesdecisions",children:"services.decisions"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.decisions object"',children:'{\n "decide": (request: ContextualBanditRequest): Item[]\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"servicescorvus",children:"services.corvus"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.corvus object"',children:'{\n "contextualBandit": {\n "decide": (request: ContextualBanditRequest, filter: PromotionFilter): Item[]\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"servicespromotioncatalog",children:"services.promotionCatalog"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.promotionCatalog object"',children:'{\n "findPromotions": (filter: ItemFilter, context: CampaignComponentContext): Promotion: [],\n "promotionFilter": (contentZone: string): PromotionFilter\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h2,{id:"user",children:"user"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user"})," is the most significant property, covering tons of information about the user that triggered the campaign. It contains multiple subobjects and methods perfect for statistics-based use cases within the serverside code."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user object"',children:'{\n "attributes": Object,\n "profileObjects": Object,\n "visits": [Object],\n "orderHistory": [Object],\n "location": Object,\n "currentCart": Object,\n "anonymous": boolean,\n "segmentMembership": [Object],\n "id": string,\n actionCount: (request: ActionStatsRequest): number,\n actionCountPerItem: (request: ActionStatsRequest): Object,\n getDimensionActivity: (dimension: string, start: Date, end: Date): {\n [itemId: string]: ItemActionStats\n },\n getDimensionActivityByDay: (dimension: string, start: Date, end: Date): {\n [date: string] : ItemActionStats\n },\n getEmailSendHistory: (start: Date, end: Date): EmailSendActivity[] || (): EmailSendActivity[],\n getLatestOrderByStatus: (status: \'Open\' | \'Purchased\' | \'Cancelled\'): Order,\n getSegmentJoinDate: (segmentId: string): Date,\n itemStatTotal: (request: ItemStatsRequest): number,\n itemStatTotalPerItem: (request: ItemStatsRequest): ItemStat[],\n pageViewCount: (request: StatsRequest): number,\n visitCount: (request: StatsRequest): number,\n visitDurationMillis: (request: StatsRequest): number,\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Let's start our discovery of ",(0,s.jsx)(t.code,{children:"context.user"})," with the methods."]}),"\n",(0,s.jsx)(t.h3,{id:"user-methods",children:"user methods"}),"\n",(0,s.jsx)(t.h4,{id:"contextuseractioncount",children:"context.user.actionCount()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires an ActionStatsRequest (",(0,s.jsx)(t.code,{children:"{actionName: 'Name of the action'}"}),") and returns the total of provided action triggers for the current user. You can also extend ActionStatsRequest with ",(0,s.jsx)(t.code,{children:"start"})," or ",(0,s.jsx)(t.code,{children:"end"})," (but not both) date properties to limit the timeframe of the action count."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3} title="Check how many times customer viewed cart within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst homeViewCount = context.user.actionCount({actionName: 'Viewed Cart', start: yesterday}); // Returns: 4\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextuseractioncountperitem",children:"context.user.actionCountPerItem()"}),"\n",(0,s.jsxs)(t.p,{children:["In theory, it should be able to return the action count per item (after passing a ",(0,s.jsx)(t.code,{children:"'Viewed Product'"})," action in ActionStatsRequest, it should show the counts per each product where that action triggered). But it doesn't. It returns the same information as the ",(0,s.jsx)(t.a,{href:"#contextuseractioncount",children:(0,s.jsx)(t.code,{children:"actionCount()"})})," method, but instead of doing it directly as a number, it does it as an object with an action name. Unless I'm missing something, it's useless."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Full on promise, null on delivery actionCountPerItem method"',children:"const homeViewCount = context.user.actionCountPerItem({actionName: 'Viewed Product'}); // Returns: {'Viewed Product': 5}\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetdimensionactivity",children:"context.user.getDimensionActivity()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires a dimension (a Catalog, like ",(0,s.jsx)(t.code,{children:"'Product'"}),", '",(0,s.jsx)(t.code,{children:"Category"}),"' or ",(0,s.jsx)(t.code,{children:"'CustomCatalog'"}),") and start + end date boundaries. This time, you must always provide both in that exact order. The significant difference with this method is that you pass direct arguments, not a grouping Stat object. It returns an object with Item IDs and related activity data from the selected Dimension with which the user interacted during the timeframe."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3,5} title="Find the activity in a specified catalog"',children:'const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst brandActivity = context.user.getDimensionActivity(\'Brand\', yesterday, today); // Returns:\n// {\n// "Apple": {\n// "view": 2,\n// "viewOutOfStock": 0,\n// "viewDetail": 0,\n// "viewTime": 43339,\n// "cart": 1,\n// "cartValue": 215,\n// "purchase": 1,\n// "purchaseValue": 215,\n// "review": 0,\n// "share": 0,\n// "comment": 0,\n// "favorite": 0\n// }\n// }\n'})}),"\n",(0,s.jsx)(t.p,{children:"That's an excellent set of data to calculate the most viewed Category, longest viewed Product, or most purchased Brand by that specific user. Unfortunately, it's still just a proxy for the actual affinity data, which is unavailable."}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["While you can work on the returned object, you cannot directly pass it to the serverside payload. You can output the final value (f.e. ",(0,s.jsx)(t.code,{children:"brandActivity.Apple.view"}),"), but both ",(0,s.jsx)(t.code,{children:"brandActivity"})," and ",(0,s.jsx)(t.code,{children:"brandActivity.Apple"})," will break it."]}),(0,s.jsxs)(t.p,{children:["You can perform calculations in serverside code on any level, but if you need to output it directly in the payload, there is a trick: ",(0,s.jsx)(t.code,{children:"JSON.parse(JSON.strinify(brandActivity))"}),"."]})]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetdimensionactivitybyday",children:"context.user.getDimensionActivityByDay()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"getDimensionActivityByDay"})," method works nearly the same as ",(0,s.jsx)(t.a,{href:"#contextusergetdimensionactivity",children:(0,s.jsx)(t.code,{children:"getDimensionActivity"})}),". There are two key differences:"]}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"It requires additional argument - right after selecting the Dimension, you must also pass the specific Item ID for which you want to see the activity."}),"\n",(0,s.jsx)(t.li,{children:"The returned Object will have epoch properties for each activity day within the selected period."}),"\n"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3,5} title="Find the activity in a specified catalog"',children:'const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst brandActivity = context.user.getDimensionActivityByDay(\'Brand\', \'Apple\', yesterday, today); // Returns:\n// {\n// "1707782400000": {\n// "view": 2,\n// "viewOutOfStock": 0,\n// "viewDetail": 0,\n// "viewTime": 43339,\n// "cart": 1,\n// "cartValue": 215,\n// "purchase": 1,\n// "purchaseValue": 215,\n// "review": 0,\n// "share": 0,\n// "comment": 0,\n// "favorite": 0\n// }\n// }\n'})}),"\n",(0,s.jsxs)(t.p,{children:["It also has the same payload limitation as ",(0,s.jsx)(t.a,{href:"#contextusergetdimensionactivity",children:(0,s.jsx)(t.code,{children:"getDimensionActivity"})}),", and the same workaround is available."]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetemailsendhistory",children:"context.user.getEmailSendHistory()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires either nothing or start/end data boundary and returns... nothing. At least I couldn't get it to work with the ",(0,s.jsx)(t.a,{href:"/docs/interaction-studio/mcp-open-time-email",children:"OTE Campaign"})," data. It may leverage the barely working ",(0,s.jsx)(t.a,{href:"../../../sites/ideas/mc-personalization-ideas#external-email-campaign-etl-send-segmentation",children:"External Email Campaign ETL"}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetlatestorderbystatus",children:"context.user.getLatestOrderByStatus()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires an order status (",(0,s.jsx)(t.code,{children:"'Open'"}),", ",(0,s.jsx)(t.code,{children:"'Purchased'"})," or ",(0,s.jsx)(t.code,{children:"'Cancelled'"}),") and returns the most recent Order object in the selected state. The data structure and content are the same as in the ",(0,s.jsx)(t.a,{href:"#userorderhistory",children:(0,s.jsx)(t.code,{children:"user.orderHistory"})}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetsegmentjoindate",children:"context.user.getSegmentJoinDate()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires Segment ID (you can view it in User Segments after you add the ID column or by opening a specific segment and copying five alphanumerical characters from URL: ",(0,s.jsx)(t.code,{children:".../segment/{SegmentID}/members..."}),") and returns an epoch with join date. It's a fantastic way to capture additional context for the user (f.e. how many days ago he joined the Gold Tier segment)."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Segment join epoch fun"',children:"const segmentJoinEpoch = context.user.getSegmentJoinDate('qWeR1'); // Returns: 1695796858287\n"})}),"\n",(0,s.jsxs)(t.p,{children:["If the Segment ID is incorrect or the user has not joined the provided segment, it will return ",(0,s.jsx)(t.code,{children:"null"}),"."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsx)(t.p,{children:"You can easily convert epoch to date to simplify date calculations:"}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2,7} title="Perform date comparisons on epoch"',children:"const segmentJoinEpoch = context.user.getSegmentJoinDate('qWeR1'); // Returns: 1695796858287\nconst segmentJoinDate = new Date(segmentJoinEpoch);\n\nconst today = new Date();\nconst lastWeek = new Date(today.setDate(today.getDate() - 7));\n\nconst hasJoinedLastWeek = segmentJoinDate > lastWeek;\n"})})]}),"\n",(0,s.jsx)(t.h4,{id:"contextuseritemstattotal",children:"context.user.itemStatTotal()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires an ItemStatsRequest (",(0,s.jsx)(t.code,{children:"{itemType: 'CatalogName', statType: 'StatTypeName'}"}),") and returns the count for that stat for a given Catalog. You can also extend ItemStatsRequest with another optional property ",(0,s.jsx)(t.code,{children:"itemId: 'id'"})," to limit the result to a specific Item within a given Catalog (itemType). Finally, as with ",(0,s.jsx)(t.a,{href:"#contextuseractioncount",children:"actionCount()"}),", you can also use ",(0,s.jsx)(t.code,{children:"start"})," or ",(0,s.jsx)(t.code,{children:"end"})," timeframe boundaries - but not both."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-8} title="Time spent by the user on Laptop Category within the last day in milliseconds"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.itemStatTotal({\n itemId: 'Laptop',\n itemType: 'Category',\n statType: 'ViewTime',\n start: yesterday\n}); // Returns: 98663\n"})}),"\n",(0,s.jsx)(t.p,{children:"Available statTypes: 'View', 'ViewOutOfStock', 'ViewValue', 'ViewDetail', 'QuickView', 'ViewTime', 'Cart', 'CartValue', 'Purchase', 'Visit', 'PurchaseValue', 'Review', 'Share', 'Comment', 'Favorite', 'Searches', 'SearchClicks', 'ClickThrough', 'RemoveFromCart', 'RemoveFromCartValue', 'RecommendedCount', 'PageLoadTime', 'PageLoadTimeCount', 'DomLoadTime', 'DomLoadTimeCount', 'TwReceiverTime', 'TwReceiverTimeCount', 'NumErrorEvents', 'TriggeredCount', 'RequestedForServing', 'EligibleForServing', 'Served'."}),"\n",(0,s.jsx)(t.p,{children:"Remember that the meaning of the returned value will differ depending on the selected statType - it can be count, milliseconds or money."}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsxs)(t.p,{children:["This method works perfectly with the ",(0,s.jsx)(t.a,{href:"#contexteventitemid",children:(0,s.jsx)(t.code,{children:"context.event.itemId()"})})," and ",(0,s.jsx)(t.a,{href:"#contexteventitemtype",children:(0,s.jsx)(t.code,{children:"context.event.itemType()"})})," as with those, you can pull relevant stats for a currently viewed Item and adapt payload for it (f.e. adapt Exit Intent incentive based on the number of visits or time spent on currently viewed product)."]})}),"\n",(0,s.jsx)(t.h4,{id:"contextuseritemstattotalperitem",children:"context.user.itemStatTotalPerItem()"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"itemStatsPerItem()"})," works in a very similar manner to ",(0,s.jsx)(t.a,{href:"#contextuseritemstattotal",children:(0,s.jsx)(t.code,{children:"itemStatsTotal()"})})," and accepts the same ItemStatsRequest. The key difference is that instead of a single value, it will return an array of objects, each containing an itemId and value specific to that item."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-7} title="Time spent by the user on Products within the last day in milliseconds"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.itemStatPerItem({\n itemType: 'Product',\n statType: 'ViewTime',\n start: yesterday\n}); // Returns: [{itemId: '123', value: 9238}, {itemId: '456', value: 26651}]\n"})}),"\n",(0,s.jsxs)(t.p,{children:["While you can pass ",(0,s.jsx)(t.code,{children:"itemId: 'id'"})," in the ItemStatsRequest, it will limit the outputted array to a single object for that item, making it not useful vs ",(0,s.jsx)(t.a,{href:"#contextuseritemstattotal",children:(0,s.jsx)(t.code,{children:"itemStatsTotal()"})}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contextuserpageviewcount",children:"context.user.pageViewCount()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires StatsRequest (",(0,s.jsx)(t.code,{children:"{start: Date, end: Date}"})," - use either start or end; using both will always return 0) and returns the count of pages viewed in that timeframe. Both timeframe bounds are required."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-6} title="Pages viewed within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.pageViewCount({\n start: yesterday\n}); // Returns: 9\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextuservisitcount",children:"context.user.visitCount()"}),"\n",(0,s.jsxs)(t.p,{children:["Similar to ",(0,s.jsx)(t.a,{href:"#contextuserpageviewcount",children:"pageViewCount()"}),", it requires StatsRequest (",(0,s.jsx)(t.code,{children:"{start: Date, end: Date}"})," - use either start or end; using both will always return 0) but returns the count of visits instead of specific pages."]}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsx)(t.p,{children:"Visit for Marketing Cloud Personalization starts from the first page view and ends after the user reaches 30 minutes of inactivity on the site. So if a user goes to your website to view a few pages, leaves and then returns after 40 minutes - it will be counted as a separate visit."})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-6} title="Visits within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.visitCount({\n start: yesterday\n}); // Returns: 2\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextuservisitdurationmilis",children:"context.user.visitDurationMilis()"}),"\n",(0,s.jsxs)(t.p,{children:["Similar to ",(0,s.jsx)(t.a,{href:"#contextuserpageviewcount",children:"pageViewCount()"}),", it requires StatsRequest (",(0,s.jsx)(t.code,{children:"{start: Date, end: Date}"})," - use either start or end, using both will always return 0) but returns the number of milliseconds the user spent on your website in a specified timeframe."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-6} title="Visits within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.visitDurationMilis({\n start: yesterday,\n end: today\n}); // Returns: 98663\n"})}),"\n",(0,s.jsx)(t.h3,{id:"userattributes",children:"user.attributes"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.attributes"})," object contains out-of-the-box, custom and hidden attributes with respective values for the user. It's an instrumental part of the ",(0,s.jsx)(t.code,{children:"context"})," as it allows you to pull user-specific data not only from the triggering event (like it is also possible with ",(0,s.jsx)(t.a,{href:"#contexteventfieldscustomattribute",children:(0,s.jsx)(t.code,{children:"context.event.fields.customAttribute"})}),") but also from past events. This enables fun use cases like saving in custom attributes the last viewed Product and Category with Sitemap and then leveraging that information when the user is on the non-product page of your website to bring them back onto the funnel. It's also great to personalize your campaign (f.e. with the first name in the info banner or overlay)."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.attributes object"',children:'{\n "created": {\n "value": number // epoch\n },\n "customAttribute": {\n "value": any\n },\n "originatingReferrer": {\n "value": "{\\"medium\\":\\"Direct\\",\\"source\\":null,\\"terms\\":null,\\"domain\\":null,\\"subdomainReversed\\":null,\\"url\\":null,\\"landingUrl\\":\\"https://www.mateuszdabrowski.pl/\\"}"\n },\n "firstName": {\n "value": string\n },\n "lastViewedCartAt": {\n "value": number // epoch\n },\n "firstActivity": {\n "value": number // epoch\n }\n}\n'})}),"\n",(0,s.jsx)(t.h3,{id:"userprofileobjects",children:"user.profileObjects"}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"uservisits",children:"user.visits"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.visits"})," is an Array with user visits. Remember that the Marketing Cloud Personalization visit starts from the first page view and ends after the user reaches 30 minutes of inactivity on the site. So if a user goes to your website to view a few pages, leaves and then returns after 40 minutes - it will be counted as a separate visit. It is critical - there is no way to access the history of each page the user visits. You can only see the visit (session start data) with a ",(0,s.jsx)(t.code,{children:"pageViewIndex"})," with a count of page views during that visit."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.visits array"',children:'[\n {\n "start": number, // epoch\n "lastEventTime": number, // epoch\n "timeSinceLastVisit": number, // milliseconds\n "referrer": { // || null\n "medium": "Direct",\n "source": null,\n "terms": null,\n "domain": null,\n "subdomainReversed": null,\n "url": null,\n "landingUrl": "https://www.mateuszdabrowski.pl/"\n },\n "deviceType": "Computer",\n "browser": "Chrome",\n "platform": "Web",\n "operatingSystem": "Windows",\n "weather": { // || null\n "temperature": 71,\n "humidity": 67,\n "windSpeed": 7,\n "rain3h": 0,\n "snow3h": 0,\n "cloudCoverage": 0,\n "condition": {\n "id": 800,\n "name": "clear sky",\n "icon": "01d",\n "category": "Clear"\n }\n },\n "pageViewIndex": 9\n }\n]\n'})}),"\n",(0,s.jsx)(t.p,{children:"While there are a few attributes here, I would like to focus on two that enable exciting use cases:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"referrer"})," can contain data of the website that led the user to you. If this is the case, you can create a dedicated campaign focusing on the source (f.e. small vouchers to convert people coming from voucher-gathering websites) or terms (f.e. changing the experience based on social ad terms passed)."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"weather"})," can provide you with details about temperature, rain and snow, unlocking like-magic use cases, f.e. if it is cold and showers for your customer, display a campaign with a dedicated message promoting a sunny and hot travel destination."]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"userorderhistory",children:"user.orderHistory"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.orderHistory"})," is an array with past orders in any status (open, purchased or cancelled) for the user. It contains everything - timeframes, order value and currency and even a list of all products in that order."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.orderHistory array"',children:'[\n {\n "id": null,\n "created": number, // epoch\n "updated": number, // epoch\n "purchaseDate": null,\n "visitAgeAtPurchase": number, // milliseconds\n "totalValue": number,\n "totalValueCurrency": null,\n "status": "Open",\n "metadata": null,\n "lineItems": [\n {\n "quantity": number,\n "price": number,\n "itemId": string,\n "attributes": {}\n },\n ],\n "attributes": {}\n }\n]\n'})}),"\n",(0,s.jsx)(t.h3,{id:"userlocation",children:"user.location"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.location"})," can be magic or trash - depending on the Internet Service Providers of your audience. The rule of thumb is good data for B2B and mixed data for B2C. It's worth checking because if you can trust/clean this data, you can do astounding things with it."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.location object"',children:'{\n "geographicPoint": {\n "latitude": number,\n "longitude": number\n },\n "timeZoneId": "Europe/Warsaw",\n "continentKey": "EU",\n "countryCode": "PL",\n "countryNumericCode": 616,\n "stateProvinceCode": "14",\n "city": "Warsaw",\n "postalCode": "00-633",\n "organization": "Pwc Polska Sp. Z O.o.",\n "naicsCode": "517311"\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Firstly, ",(0,s.jsx)(t.code,{children:"context.user.location.geographicPoint"})," contains latitude and longitude that can be perfect for ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog.findClosestItems()"})})," call."]}),"\n",(0,s.jsxs)(t.p,{children:["Secondly, if you target B2B customers and get organisation details (the example above is real - it returned all those details when I checked it from the PwC Poland office), it can help you get precious information about your known ",(0,s.jsx)(t.strong,{children:"and anonymous"})," visitors! However, a (big) grain of salt is needed - the NAICS Code (2017 NAICS Definition) returned for me Wired Telecommunications Carriers, which looks like code for Internet Services Provider, not PwC. For B2C, the ",(0,s.jsx)(t.code,{children:"organisation"})," field will return the Internet Service Provider name in most cases."]}),"\n",(0,s.jsx)(t.h3,{id:"usercurrentcart",children:"user.currentCart"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.currentCart"})," is a single object with the same structure as each of the orders stored in ",(0,s.jsx)(t.a,{href:"#userorderhistory",children:(0,s.jsx)(t.code,{children:"context.user.orderHistory"})}),". But because it is still a cart, not an order, most fields will be ",(0,s.jsx)(t.code,{children:"null"}),"/",(0,s.jsx)(t.code,{children:"0"}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.currentCart object"',children:'{\n "id": null,\n "created": number, // epoch\n "updated": number, // epoch\n "purchaseDate": null,\n "visitAgeAtPurchase": 0,\n "totalValue": 0,\n "totalValueCurrency": null,\n "status": "Open",\n "metadata": null,\n "lineItems": [\n {\n "quantity": number,\n "price": number,\n "itemId": string,\n "attributes": {}\n },\n ],\n "attributes": {}\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"The fun use case here is checking when the user updated the cart and, if enough time has passed, leveraging the lineItems to deploy an abandoned basket Web Campaign."}),"\n",(0,s.jsx)(t.h3,{id:"usersegmentmembership",children:"user.segmentMembership"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.segmentMembership"})," is an array with segments the user is a member of. With a good segmentation naming convention, the ",(0,s.jsx)(t.code,{children:"segmentName"})," and ",(0,s.jsx)(t.code,{children:"joined"})," can capture valuable additional context for the user (f.e. how many days ago he joined the Gold Tier segment or became an at-risk customer)."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.segmentMembership array"',children:'[\n {\n "segmentId": string,\n "segmentName": string,\n "joined": number, // epoch\n "createIfMissing": boolean,\n "removal": boolean,\n "userId": string,\n "customerId": string,\n "customerType": "User"\n }\n]\n'})}),"\n",(0,s.jsx)(t.h2,{id:"accountid--datasetid",children:"accountId & datasetId"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"accountId"})," and ",(0,s.jsx)(t.code,{children:"datasetId"})," are string properties that contain information about the Marketing Cloud Personalization account and dataset that generated the event. It is only handy if you want environment-aware debug log visibility logic."]}),"\n",(0,s.jsx)(t.h2,{id:"configuration",children:"configuration"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"configuration"})," object property contains information about the campaign properties (fields you expect the marketer to fill in when configuring the campaign) in the experience for a given user. Not really useful, as in the serverside code, you can access the same information using the ",(0,s.jsx)(t.code,{children:"this"})," keyword (f.e. ",(0,s.jsx)(t.code,{children:"this.campaignPropertyName"}),")."]})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},6748:(e,t,n)=>{n.d(t,{U:()=>r});const s="leadText_qzwo";var i=n(4848);const r=e=>{let{content:t}=e;return(0,i.jsx)(i.Fragment,{children:(0,i.jsx)("p",{id:s,children:t})})}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const i={},r=s.createContext(i);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmd=self.webpackChunkmd||[]).push([[3823],{4519:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var s=n(4848),i=n(8453),r=n(6748);const o={id:"mcp-serverside-code-context",title:"MCP Serverside Code Context",sidebar_label:"Serverside Code Context",description:"Context is king. Also when writing MCP Template Serverside Code.",image:"img/og/og-image-mcp-serverside-code-context.png",tags:["Marketing Cloud","Marketing Cloud Personalization","Interaction Studio","Personalisation","TypeScript"]},a=void 0,c={id:"interaction-studio/mcp-serverside-code-context",title:"MCP Serverside Code Context",description:"Context is king. Also when writing MCP Template Serverside Code.",source:"@site/docs/interaction-studio/mcp-serverside-code-context.mdx",sourceDirName:"interaction-studio",slug:"/interaction-studio/mcp-serverside-code-context",permalink:"/docs/interaction-studio/mcp-serverside-code-context",draft:!1,unlisted:!1,editUrl:"https://github.com/MateuszDabrowski/mateuszdabrowski.pl/edit/master/docs/interaction-studio/mcp-serverside-code-context.mdx",tags:[{inline:!0,label:"Marketing Cloud",permalink:"/docs/tags/marketing-cloud"},{inline:!0,label:"Marketing Cloud Personalization",permalink:"/docs/tags/marketing-cloud-personalization"},{inline:!0,label:"Interaction Studio",permalink:"/docs/tags/interaction-studio"},{inline:!0,label:"Personalisation",permalink:"/docs/tags/personalisation"},{inline:!0,label:"TypeScript",permalink:"/docs/tags/type-script"}],version:"current",lastUpdatedBy:"Mateusz D\u0105browski",lastUpdatedAt:1728481186e3,frontMatter:{id:"mcp-serverside-code-context",title:"MCP Serverside Code Context",sidebar_label:"Serverside Code Context",description:"Context is king. Also when writing MCP Template Serverside Code.",image:"img/og/og-image-mcp-serverside-code-context.png",tags:["Marketing Cloud","Marketing Cloud Personalization","Interaction Studio","Personalisation","TypeScript"]},sidebar:"docs",previous:{title:"Serverside Code Properties",permalink:"/docs/interaction-studio/mcp-serverside-code-properties"},next:{title:"\u203a MC Personalization Snippets",permalink:"/docs/category/-mc-personalization-snippets"}},d={},l=[{value:"campaignId & experienceId",id:"campaignid--experienceid",level:2},{value:"userGroup",id:"usergroup",level:2},{value:"beaconVersion",id:"beaconversion",level:2},{value:"event",id:"event",level:2},{value:"event methods",id:"event-methods",level:3},{value:"context.event.ipAddress()",id:"contexteventipaddress",level:4},{value:"context.event.itemId()",id:"contexteventitemid",level:4},{value:"context.event.itemType()",id:"contexteventitemtype",level:4},{value:"event.fields",id:"eventfields",level:3},{value:"context.event.fields.pageType",id:"contexteventfieldspagetype",level:4},{value:"context.event.fields.action",id:"contexteventfieldsaction",level:4},{value:"context.event.fields.url",id:"contexteventfieldsurl",level:4},{value:"context.event.fields.customAttribute",id:"contexteventfieldscustomattribute",level:4},{value:"contentZone",id:"contentzone",level:2},{value:"trigger",id:"trigger",level:2},{value:"locale",id:"locale",level:2},{value:"services",id:"services",level:2},{value:"services.catalog",id:"servicescatalog",level:3},{value:"context.services.catalog.findItem()",id:"contextservicescatalogfinditem",level:4},{value:"context.services.catalog.findItems()",id:"contextservicescatalogfinditems",level:4},{value:"context.services.catalog.findClosestItems()",id:"contextservicescatalogfindclosestitems",level:4},{value:"context.services.catalog.dimensionFilter()",id:"contextservicescatalogdimensionfilter",level:4},{value:"services.recommendations",id:"servicesrecommendations",level:3},{value:"context.services.recommendations.recommend()",id:"contextservicesrecommendationsrecommend",level:4},{value:"context.services.recommendations.recommendIdsOnly()",id:"contextservicesrecommendationsrecommendidsonly",level:4},{value:"context.services.recommendations.smartSearch()",id:"contextservicesrecommendationssmartsearch",level:4},{value:"context.services.recommendations.smartSort()",id:"contextservicesrecommendationssmartsort",level:4},{value:"services.smartTrends",id:"servicessmarttrends",level:3},{value:"services.surveys",id:"servicessurveys",level:3},{value:"services.decisions",id:"servicesdecisions",level:3},{value:"services.corvus",id:"servicescorvus",level:3},{value:"services.promotionCatalog",id:"servicespromotioncatalog",level:3},{value:"user",id:"user",level:2},{value:"user methods",id:"user-methods",level:3},{value:"context.user.actionCount()",id:"contextuseractioncount",level:4},{value:"context.user.actionCountPerItem()",id:"contextuseractioncountperitem",level:4},{value:"context.user.getDimensionActivity()",id:"contextusergetdimensionactivity",level:4},{value:"context.user.getDimensionActivityByDay()",id:"contextusergetdimensionactivitybyday",level:4},{value:"context.user.getEmailSendHistory()",id:"contextusergetemailsendhistory",level:4},{value:"context.user.getLatestOrderByStatus()",id:"contextusergetlatestorderbystatus",level:4},{value:"context.user.getSegmentJoinDate()",id:"contextusergetsegmentjoindate",level:4},{value:"context.user.itemStatTotal()",id:"contextuseritemstattotal",level:4},{value:"context.user.itemStatTotalPerItem()",id:"contextuseritemstattotalperitem",level:4},{value:"context.user.pageViewCount()",id:"contextuserpageviewcount",level:4},{value:"context.user.visitCount()",id:"contextuservisitcount",level:4},{value:"context.user.visitDurationMilis()",id:"contextuservisitdurationmilis",level:4},{value:"user.attributes",id:"userattributes",level:3},{value:"user.profileObjects",id:"userprofileobjects",level:3},{value:"user.visits",id:"uservisits",level:3},{value:"user.orderHistory",id:"userorderhistory",level:3},{value:"user.location",id:"userlocation",level:3},{value:"user.currentCart",id:"usercurrentcart",level:3},{value:"user.segmentMembership",id:"usersegmentmembership",level:3},{value:"accountId & datasetId",id:"accountid--datasetid",level:2},{value:"configuration",id:"configuration",level:2}];function h(e){const t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.U,{content:"Context is king. Also when coding MCP Campaign Templates. Read about all its undocumented tricks."}),"\n",(0,s.jsxs)(t.p,{children:["Marketing Cloud Personalization offers flexible campaign template creation tooling with multiple ",(0,s.jsx)(t.a,{href:"/docs/interaction-studio/mcp-serverside-code-properties",children:"properties"})," and imports that help you fulfil business needs while providing a pleasant user experience for the marketer. There is also one more\u2014undocumented\u2014feature that can change your template from good to outstanding: the CampaignComponentContext object."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["In this article, I'm covering the main ",(0,s.jsx)(t.code,{children:"CampaignComponentContext"})," object that is passed as a ",(0,s.jsx)(t.code,{children:"context"})," argument to the ",(0,s.jsxs)(t.a,{href:"/docs/interaction-studio/mcp-serverside-code-basics#writing-serverside-code",children:[(0,s.jsx)(t.code,{children:"run"})," block"]})," in the Serverside Code of every campaign template."]}),(0,s.jsxs)(t.p,{children:["Some other contexts (like ",(0,s.jsx)(t.code,{children:"GearLifecycleContext"})," passed to search methods) have different structures and are out of the scope of this article."]})]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"CampaignComponentContext"})," object is available in the Serverside Code of the Web, Serverside and Triggered Campaign Templates and provides extensive details about triggering event, user and delivered experience."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context object"',children:'{\n "campaignId": string,\n "experienceId": string,\n "userGroup": string,\n "beaconVersion": number,\n "event": Object,\n "contentZone": string,\n "trigger": Object,\n "locale": string,\n "services": Object,\n "user": Object,\n "accountId": string,\n "datasetId": string,\n "configuration": Object\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"It's straightforward to use once you know what's in there. For example, you can pull product ID stored with Sitemap in a User Attribute and leverage it to pull complete data about that product for personalisation:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2-3} title="Leverage context in the run method of your Serverside Code"',children:" run(context: CampaignComponentContext) {\n const lastAddedToCartProductId = context.user.attributes?.lastAddedToCartProduct?.value;\n const lastAddedToCartProductDetails = context.services.catalog.findItem('Product', lastAddedToCartProductId);\n return { lastATCDetails: lastAddedToCartProductDetails };\n }\n"})}),"\n",(0,s.jsxs)(t.p,{children:["And that's just a basic usage. The key to unlocking the power of a context object is knowing what is stored there and how to use it. So let's dive in, property by property (hint: the fun part starts at ",(0,s.jsx)(t.a,{href:"#event",children:(0,s.jsx)(t.code,{children:"event"})}),")."]}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsx)(t.p,{children:"This article is a work in progress. I'm continually extending details about various parts of the context object as I use it in real life."})}),"\n",(0,s.jsx)(t.h2,{id:"campaignid--experienceid",children:"campaignId & experienceId"}),"\n",(0,s.jsxs)(t.p,{children:["The first two string properties of the context object are ",(0,s.jsx)(t.code,{children:"campaignId"})," and ",(0,s.jsx)(t.code,{children:"experienceId"}),", and their purpose is very straightforward. They provide the five-character, case-sensitive, alphanumerical IDs for the campaign and experience selected for a user (for example, ",(0,s.jsx)(t.code,{children:"vALdQ"})," for Campaign ID and ",(0,s.jsx)(t.code,{children:"f3WpK"})," for Experience ID)."]}),"\n",(0,s.jsxs)(t.p,{children:["Both those values are passed by default from serverside to clientside and handlebars (as ",(0,s.jsx)(t.code,{children:"campaign"})," and ",(0,s.jsx)(t.code,{children:"experience"})," accordingly), so there is not much added value in the two unless you want to append those values as query strings to the links for tracking purposes."]}),"\n",(0,s.jsx)(t.p,{children:"However, for Web Campaigns, you can do it easily within the handlebars tab, and for Serverside and Triggered Campaigns, you can do it on the receiving system side."}),"\n",(0,s.jsx)(t.h2,{id:"usergroup",children:"userGroup"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"userGroup"})," string property should tell you the group assigned to the user. Well, it should. In practice, you will see there one of the two values: ",(0,s.jsx)(t.code,{children:"Test"})," for users that got an A/B Test or Rule-Based experience and ",(0,s.jsx)(t.code,{children:"testUserGroup"})," for those that are in the Control group (or in the Template preview pane within MCP UI)."]}),"\n",(0,s.jsxs)(t.p,{children:["However, you will see better values in the out-of-the-box serverside payload ",(0,s.jsx)(t.code,{children:"userGroup"})," property that correctly shows values like ",(0,s.jsx)(t.code,{children:"Test"}),", ",(0,s.jsx)(t.code,{children:"Default"}),", and ",(0,s.jsx)(t.code,{children:"Control"})," and only displays ",(0,s.jsx)(t.code,{children:"testUserGroup"})," during preview."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["The control group creates more problems for the context, as it keeps displaying the payload preview version of it. So you will also see only the placeholder values for ",(0,s.jsxs)(t.a,{href:"#campaignid--experienceid",children:[(0,s.jsx)(t.code,{children:"campaignId"})," and ",(0,s.jsx)(t.code,{children:"experienceId"})]}),", ",(0,s.jsx)(t.a,{href:"#beaconversion",children:(0,s.jsx)(t.code,{children:"beaconVersion"})})," and skip other datapoints like ",(0,s.jsx)(t.a,{href:"#event",children:(0,s.jsx)(t.code,{children:"event.fields"})}),"."]}),(0,s.jsxs)(t.p,{children:["In short, don't use ",(0,s.jsx)(t.code,{children:"context"})," for custom payload dedicated to control group users."]})]}),"\n",(0,s.jsx)(t.h2,{id:"beaconversion",children:"beaconVersion"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"beaconVersion"})," number property will display the current Web SDK version (e.g., ",(0,s.jsx)(t.code,{children:"16"})," at the time of writing) or ",(0,s.jsx)(t.code,{children:"0"})," for the preview/control group. Not really useful."]}),"\n",(0,s.jsx)(t.h2,{id:"event",children:"event"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"event"})," object property is where the magic of the ",(0,s.jsx)(t.code,{children:"context"})," object starts. It stores information about the event that triggered the campaign - the data you can see when you leverage the ",(0,s.jsx)(t.code,{children:".setLoggingLevel('debug')"})," method in your Sitemap."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"context.event"})," object won't work correctly in the Template Preview sidebar, as there is no valid event in that mode. Use an active campaign directly on the website to preview the actual output during development. Make sure you use the campaign targeting to limit execution just to you."]}),(0,s.jsxs)(t.p,{children:["In Template Preview, you will only be able to use ",(0,s.jsx)(t.a,{href:"#eventfields",children:(0,s.jsx)(t.code,{children:"context.event.fields.item"})})," - a single property with a stringified object containing details of the Item selected in the top right Simulate section):"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{children:'"{\\"type\\":\\"ITEM_TYPE\\",\\"_id\\":{\\"label\\":\\"ITEM_LABEL\\",\\"value\\":\\"ITEM_ID\\"}}"\n'})}),(0,s.jsxs)(t.p,{children:["My ",(0,s.jsx)(t.a,{href:"/docs/interaction-studio/snippets/mcp-catalog-etl-metadata-viewer",children:"MCP Catalog ETL Metadata Viewer"})," provides an example of its usage."]})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.event object"',children:'{\n "time": datetime,\n "fields": Object,\n "ipAddress": (): string,\n "itemId": (): string,\n "itemType": (): string\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["While the ",(0,s.jsx)(t.code,{children:"context.event.time"})," is not that useful (unless you want to make some time-dependent changes to the campaign payload), the three available methods are much more practical."]}),"\n",(0,s.jsx)(t.h3,{id:"event-methods",children:"event methods"}),"\n",(0,s.jsx)(t.h4,{id:"contexteventipaddress",children:"context.event.ipAddress()"}),"\n",(0,s.jsx)(t.p,{children:"Returns an IP address of the user visiting your website. You might use it to blocklist specific IP ranges (internal or competitors) from seeing your campaigns. It's not a clean solution (as the campaign needs to be executed to get this far), but this might be your best bet, as there is no MCP-level IP blocklist. Of course, a much better solution would be to build such logic on the website side to block IPs already on the Web SDK import step conditionally, but that might not always be possible."}),"\n",(0,s.jsx)(t.h4,{id:"contexteventitemid",children:"context.event.itemId()"}),"\n",(0,s.jsxs)(t.p,{children:["Returns the ID of the Catalog Item the user viewed in the event. It pairs perfectly with the following method: ",(0,s.jsx)(t.code,{children:"context.event.itemType()"}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contexteventitemtype",children:"context.event.itemType()"}),"\n",(0,s.jsxs)(t.p,{children:["Returns the Catalog of the Item viewed (f.e. ",(0,s.jsx)(t.code,{children:"'Product'"})," for Product View)."]}),"\n",(0,s.jsxs)(t.p,{children:["The pair of ",(0,s.jsx)(t.code,{children:"itemId"})," and ",(0,s.jsx)(t.code,{children:"itemType"})," is handy, as those two details are precisely what MCP requires for a ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog.findItem()"})})," call that lets you get complete details about the currently displayed item. It enables use cases where you want to change the campaign payload based on displayed item attributes, related catalog objects, or other information on the item details. For example, access to ",(0,s.jsx)(t.a,{href:"#locale",children:"localized item data"}),"."]}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsxs)(t.p,{children:["Event is not only an excellent data point that you can access through ",(0,s.jsx)(t.code,{children:"context"}),". It is also the basis for the anchor in Einstein Recipes. You can leverage it (in a filthy way) to create fake anchors and deploy recommendations for products related to the one currently viewed."]})}),"\n",(0,s.jsxs)(t.p,{children:["On top of the above, ",(0,s.jsx)(t.code,{children:"context.event"})," also contains the ",(0,s.jsx)(t.code,{children:"context.event.fields"})," subobject, capturing even more details about the triggering event."]}),"\n",(0,s.jsx)(t.h3,{id:"eventfields",children:"event.fields"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.event.fields object"',children:'{\n ".anonId": string,\n ".bv": string,\n ".pv": boolean,\n ".scv": number,\n ".skipProcessing": boolean,\n "action": string,\n "channel": string,\n "clientIp": string,\n "contentZones": string[],\n "pageType": string,\n "url": string,\n "urlref": string,\n "userAgent": string,\n "_anon": boolean,\n "_debug": boolean,\n "customAttribute1": any,\n "customAttribute2": any\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.event.fields"})," subobject groups multiple data points, many of which are very technical and not really useful for us. But some can open exciting use cases - let's dive in."]}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldspagetype",children:"context.event.fields.pageType"}),"\n",(0,s.jsx)(t.p,{children:'Returns the name of the currently viewed page type as configured in the Sitemap (e.g., "Home"). This is useful when you want to adapt the campaign\'s serverside payload based on page type when the content zone is shared across many sites.'}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldsaction",children:"context.event.fields.action"}),"\n",(0,s.jsxs)(t.p,{children:["Returns the name of the currently pushed action as configured in the Sitemap (f.e. ",(0,s.jsx)(t.code,{children:"'Viewed Home'"}),"). It shines for custom action names that can drive different campaign experiences - despite being triggered on the same page type."]}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldsurl",children:"context.event.fields.url"}),"\n",(0,s.jsx)(t.p,{children:"Returns the URL where the event originated. The cool part is that it contains the hash and query strings, so you can drive use cases using those elements (f.e. change the experience based on the query string values you set in the email campaign using SFMC data)."}),"\n",(0,s.jsx)(t.h4,{id:"contexteventfieldscustomattribute",children:"context.event.fields.customAttribute"}),"\n",(0,s.jsxs)(t.p,{children:["Apart from those always-there properties, you will also see custom attributes you passed along with the event. For example, if in the Sitemap you are passing SFMC Contact Key along with the event: ",(0,s.jsx)(t.code,{children:"actionEvent.user.attributes.sfmcContactKey = queryParameters.get('sk');"})," you will have ",(0,s.jsx)(t.code,{children:"context.event.fields.sfmcContactKey"})," property available with that value. This is huge - it enables us to build campaigns leveraging real-time data. Use cases? Sure! Create an ",(0,s.jsx)(t.code,{children:"hasAddedInsurance"})," attribute filled out by the Add to Cart event to determine whether you want to promote a cross-sell. Add the ",(0,s.jsx)(t.code,{children:"hasMetFreeDeliveryThershold"})," boolean field to conditionally trigger recommendations of products that will help the customer get over the line of free delivery. The sky is the limit with those."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["If you need some data only for the specific event purpose and don't want to store it in an attribute (be it due to limits or because Sitemap cannot remove the attribute value later), you can still use the ",(0,s.jsx)(t.code,{children:"actionEvent.user.attributes.customAttribute = 'value'"})," approach to pass that information. It won't be stored on the user attribute (if there isn't one matching the name) but will still be available on the Event Stream and in the ",(0,s.jsx)(t.code,{children:"context"})," object as ",(0,s.jsx)(t.code,{children:"context.event.fields.customAttribute"}),". Works also for pushing custom events:"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'{5} title="Pushing custom event with a custom attribute that does not exist as a user attribute"',children:"Evergage.sendEvent({\n action: 'Custom Event',\n user: {\n attributes: {\n customAttribute: 'value', // You can make up any property name you want\n },\n },\n source: {\n contentZones: [{ name: 'virtual_for_global_control' }],\n }\n})\n"})})]}),"\n",(0,s.jsx)(t.h2,{id:"contentzone",children:"contentZone"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"contentZone"})," string property returns the Content Zone selected for the Campaign. It might be helpful if your campaign supports multiple content zones and you want to alter some payload elements based on the one selected (f.e. change the number of returned recommendations):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2} title="Leverage context.contentZone to change the serverside payload"',children:"// Limit the number of recommendations to the first four for smaller placements\nif (['search_see-more', 'listing_see-more'].includes(context.contentZone)) {\n recommendations = recommendations.slice(0,4);\n}\n"})}),"\n",(0,s.jsx)(t.h2,{id:"trigger",children:"trigger"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"trigger"})," object property is filled only for the Triggered Campaign Templates."]}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h2,{id:"locale",children:"locale"}),"\n",(0,s.jsxs)(t.p,{children:["If you have switched on Locale support in your Marketing Cloud Personalization, the ",(0,s.jsx)(t.code,{children:"locale"})," string will return a five-character long combination of ISO language code and ISO country code (",(0,s.jsx)(t.code,{children:"language_COUNTRY"}),", for example: ",(0,s.jsx)(t.code,{children:"en_US"})," for American English)."]}),"\n",(0,s.jsx)(t.p,{children:"You can use it to return the campaign content based on the most recent user locale (be it based on manually entered variations in the Campaign configuration or by pulling directly from the localized Catalog):"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{7} title="Leverage context.locale to pull localized product details"',children:"const recommendedIds = recommendIdsOnly(context, recipeConfig);\n// Return localized recommendations with key data points needed for the campaign\nlet localisedRecommendations = context.services.catalog\n .findItems('Product', recommendedIds)\n .map(product => product.toFlatJSON(\n ['id', 'name,' 'imageUrl', 'url', 'price'],\n context.locale || ''\n ))\n"})}),"\n",(0,s.jsx)(t.h2,{id:"services",children:"services"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.services"})," is the most potent part of the ",(0,s.jsx)(t.code,{children:"context"})," object - packed to the brim with methods that give you access to Marketing Cloud Personalization data or let you create new recommendations."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services object"',children:'{\n "catalog": Object,\n "recommendations": Object,\n "smartTrends": Object,\n "surveys": Object,\n "decisions": Object,\n "corvus": Object,\n "promotionCatalog": Object\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"It's a nested object, so let's go through it property by property to discuss each group of methods."}),"\n",(0,s.jsx)(t.h3,{id:"servicescatalog",children:"services.catalog"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"services.catalog"})," object contains a set of lookup methods that help you find Items in your Marketing Cloud Personalization Catalogs. It opens a wide range of use cases for using related Items for cross-sell and up-sell purposes."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.catalog object"',children:'{\n "dimensionFilter": (dimension: string): ItemFilter,\n "findClosestItems": (request: ClosestItemsRequest): Item[],\n "findItem": (type: string, id: string): Item,\n "findItems": (type: string, ids: string[]): Item[] || (type: ItemFilter, ids: ItemSort): Item[] || (type: ItemFilter): Item[]\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Most of those methods return an Item object - the content of it will differ depending on what type of item it is. By default, it will contain an ",(0,s.jsx)(t.code,{children:"id"})," string and an ",(0,s.jsx)(t.code,{children:"attributes"})," object with a ",(0,s.jsx)(t.code,{children:"name"}),", ",(0,s.jsx)(t.code,{children:"imageUrl"}),", ",(0,s.jsx)(t.code,{children:"description"}),", ",(0,s.jsx)(t.code,{children:"promotable"})," and ",(0,s.jsx)(t.code,{children:"archived"})," properties. Optionally, an Item can also have a ",(0,s.jsx)(t.code,{children:"dimensions"})," object with RCO's data and a ",(0,s.jsx)(t.code,{children:"location"})," object. Finally, some properties are related to a specific type of an Item - like ",(0,s.jsx)(t.code,{children:"categories"}),", ",(0,s.jsx)(t.code,{children:"skus"}),", ",(0,s.jsx)(t.code,{children:"modifiedTime"})," or ",(0,s.jsx)(t.code,{children:"subtitle"}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-json",metastring:'title="Example Item structure for a Product Catalog"',children:'{\n "id": "2050055",\n "location": null,\n "attributes": {\n "imageUrl": {\n "value": "https://www.northerntrailoutfitters.com/on/demandware.static/-/Sites-nto-apparel/default/dwf53f2476/images/large/2050055BEY-0.jpg"\n },\n "promotable": {\n "value": true\n },\n "price": {\n "value": 120\n },\n "inventoryCount": {\n "value": 1\n },\n "name": {\n "value": "Women\'s Hedgehog Agile NTO-tech"\n },\n "url": {\n "value": "https://www.northerntrailoutfitters.com/default/women%27s-hedgehog-agile-nto-tech-2050055BEY.html"\n },\n "archived": {\n "value": false\n },\n "customAttribute": {\n "value": "customValue"\n }\n },\n "dimensions": {\n "Color": [\n "AZT",\n "APD",\n "ANZ",\n "AO5",\n "BEY"\n ],\n "Feature": [\n "Waterproof",\n "Lightweight",\n "Breathable"\n ],\n "Gender": [\n "WOMEN"\n ]\n },\n "categories": [\n "WOMEN|FOOTWEAR|HIKING"\n ],\n "skus": {\n "2050055BEY": {\n "id": "2050055BEY"\n }\n }\n}\n'})}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogfinditem",children:"context.services.catalog.findItem()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"findItem()"})," is the most straightforward Catalog lookup method. It requires a Catalog Type (e.g., 'Product', 'Category', or your custom Catalog) and an Item ID (as a string) to return the full Item detail."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return Item details"',children:"const itemDetails = context.services.catalog.findItem('Product', '19542');\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It pairs perfectly with the ",(0,s.jsxs)(t.a,{href:"#event-methods",children:[(0,s.jsx)(t.code,{children:"context.event"})," methods"]})," if you want to get additional details of the currently viewed product (extremely useful when you are using ETL and strict catalog security for catalog data ingestion):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3} title="Return Item details dynamically"',children:"const itemType = context.event.itemType();\nconst itemId = context.event.itemId();\nconst itemDetails = context.services.catalog.findItem(itemType, itemId);\n"})}),"\n",(0,s.jsx)(t.p,{children:"This pairing lets us implement complex use cases like recommending direct cross-sells or up-sells using IDs passed to custom attributes on the product:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return cross and up-sell details dynamically"',children:"// Get details of the currently viewed item\nconst itemId = context.event.itemId();\nconst viewedItemDetails = context.services.catalog.findItem('Product', itemId);\n// Leverage those details to pull IDs of the hardcoded up-sell and cross-sell products\nconst upSellableItemId = viewedItemDetails.attributes?.upSellableItemId?.value;\nconst crossSellableItemId = viewedItemDetails.attributes?.crossSellableItemId?.value;\n// Pass those IDs to yet another findItem method to get full details and fill in the handlebars with data\nconst upSellableItemDetails = context.services.catalog.findItem('Product', upSellableItemId);\nconst crossSellableItemDetails = context.services.catalog.findItem('Product', crossSellableItemId);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["Of course, making so many ",(0,s.jsx)(t.code,{children:"findItem()"})," calls is not optimal, and MCP offers another method as a solution."]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogfinditems",children:"context.services.catalog.findItems()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"findItems()"})," method allows you to request details for multiple Items in a single call, which is cleaner and more performant. The baseline way of calling this function works just as ",(0,s.jsx)(t.a,{href:"#contextservicescatalogfinditem",children:(0,s.jsx)(t.code,{children:"findItem()"})}),", but it requires an array of IDs instead of a single ID and returns an array of Item detail objects instead of a single Item object."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return multiple Items details"',children:"const itemsDetails = context.services.catalog.findItem('Product', ['19542', '12524', '91324']);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["A neat use case for that method is pulling currently viewed Item details with ",(0,s.jsx)(t.a,{href:"#contextservicescatalogfinditem",children:(0,s.jsx)(t.code,{children:"findItem()"})})," to get values from a custom attribute containing alternative product IDs or dedicated accessories for it. Then, pass all those found product IDs into ",(0,s.jsx)(t.code,{children:"findItems()"})," to get the full detail required for a personalization showcasing those related items."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"findItems()"})," method offers more. You are not limited to just pushing an array of IDs like mentioned above - you can also pass an ItemFilter (created by ",(0,s.jsx)(t.a,{href:"#contextservicescatalogdimensionfilter",children:(0,s.jsx)(t.code,{children:"dimensionFilter()"})})," method) to get the IDs of items available in a custom (and only custom) Catalog."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2} title="Return multiple Items details"',children:"const catalogFilter = context.services.catalog.dimensionFilter('Color');\nconst itemsDetails = context.services.catalog.findItems(catalogFilter);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It can be further extended that custom-catalog-based approach by passing an ItemSort as a second argument. However, despite trying my luck with the ",(0,s.jsx)(t.code,{children:"sortByActivity"})," and ",(0,s.jsx)(t.code,{children:"sortByPublishedDate"})," properties, I haven't been able to make it work. That's too bad, as sorting by activity could have been interesting when working with custom Catalog Items."]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogfindclosestitems",children:"context.services.catalog.findClosestItems()"}),"\n",(0,s.jsxs)(t.p,{children:["If you are using location details for your Items, the ",(0,s.jsx)(t.code,{children:"findClosestItems()"})," method will work wonders for you as it allows you to get items based on the provided longitude and latitude within a defined distance:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2} title="Return multiple Items details"',children:"const closestDefinition = {itemType: 'Product', latitude: 52.23, longitude: 21.0118, maxDistance: 10, maxResults: 5};\nconst itemsDetails = context.services.catalog.findClosestItems(closestDefinition);\n"})}),"\n",(0,s.jsx)(t.p,{children:"As you can see, you need to provide an object with itemType, longitude and latitude, maxDistance (in miles) and maxResults as an argument. All fields are required. Of course, you don't have to hardcode it. There are two neat use cases around dynamically provided longitude and latitude:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["You can try to get longitude and latitude from ",(0,s.jsx)(t.a,{href:"#userlocation",children:(0,s.jsx)(t.code,{children:"context.user.location.geographicPoint"})}),". It allows you to make magic-like recommendations even for anonymous, first-time visits. However, confidence might be limited depending on the market specifics."]}),"\n",(0,s.jsxs)(t.li,{children:["You can capture user-provided location (based on the shipping details or the city they are filtering for on your website) and pass calculated long/lat to a user attribute. Then, use that user attribute as the source of data for the ",(0,s.jsx)(t.code,{children:"findClosestItems()"})," call to provide location-aware recommendations for your customers."]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicescatalogdimensionfilter",children:"context.services.catalog.dimensionFilter()"}),"\n",(0,s.jsxs)(t.p,{children:["As mentioned in ",(0,s.jsx)(t.a,{href:"#contextservicescatalogfinditems",children:(0,s.jsx)(t.code,{children:"findItems()"})}),", the ",(0,s.jsx)(t.code,{children:"dimensionFilter()"})," method lets us create an ItemFilter that can be leveraged to find Items from a given custom catalog (which used to be called a Dimension, hence the method name). Just pass the Catalog name as a string there. That's it."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Create an ItemFilter for Color Catalog"',children:"const catalogFilter = context.services.catalog.dimensionFilter('Color');\n"})}),"\n",(0,s.jsx)(t.h3,{id:"servicesrecommendations",children:"services.recommendations"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"services.recommendations"})," object contains four methods related to Item recommendations. Two of them are absolutely great for delivering highly customized cross-selling use cases, while the other two don't seem to work. It's a nice mixed bag. Let's dive in."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.recommendations object"',children:'{\n "recommend": (request: RecommendationsRequest): Item[],\n "recommendIdsOnly": (request: RecommendationsRequest): Item[],\n "smartSearch": (request: SmartSearchRequest): Item[],\n "smartSort": (request: SmartSort): Item[]\n}\n'})}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationsrecommend",children:"context.services.recommendations.recommend()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"recommend()"})," method is an excellent solution for generating Item recommendations in a programmatic and highly customized way. It requires ",(0,s.jsx)(t.code,{children:"currentItemId"})," and ",(0,s.jsx)(t.code,{children:"currentItemType"})," as an anchor for the Recipe, ",(0,s.jsx)(t.code,{children:"maxResults"})," to limit the number of outcomes, ",(0,s.jsx)(t.code,{children:"recipeId"})," to apply the correct recommendation model and ",(0,s.jsx)(t.code,{children:"userId"})," to pull the correct affinity data."]}),"\n",(0,s.jsxs)(t.p,{children:["Those data points can be hard coded, pulled from marketer-filled fields or captured from other context properties like ",(0,s.jsx)(t.a,{href:"#user",children:(0,s.jsx)(t.code,{children:"context.user.id"})}),", ",(0,s.jsx)(t.a,{href:"#contexteventitemid",children:(0,s.jsx)(t.code,{children:"context.event.itemId()"})})," and ",(0,s.jsx)(t.a,{href:"#contexteventitemtype",children:(0,s.jsx)(t.code,{children:"context.event.itemType()"})})," or ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog"})})," outputs."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{9} title="Return details of items recommended from a recipe"',children:"const userId = context.user.id;\nconst recommendationsRequest = {\n currentItemId: '1017847',\n currentItemType: 'Product',\n maxResults: 12,\n recipeId: '7H5OK',\n userId: userId\n}\nconst recommendedItems = context.services.recommendations.recommend(recommendationsRequest);\n"})}),"\n",(0,s.jsx)(t.p,{children:"It's a great feature for deploying recommendations that shouldn't be changed during campaign configuration, cross-selling offerings based on the currently viewed item (using its custom attributes), or filtering items based on negative recipes."}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"recommend()"})," method works just as the ",(0,s.jsx)(t.code,{children:"recommend"})," that you can import in the template along with ",(0,s.jsx)(t.code,{children:"RecommendationsConfig"})," from the ",(0,s.jsx)(t.code,{children:"recs"})," module. The imported one is better suited for the user-friendly module that the marketer can set up according to the business needs during the campaign configuration phase. The context method is better for deploying hardcoded logic programmatically without any input from the marketer\u2014the key value being the possibility of providing a custom Item anchor that might be different from the currently viewed one."]}),(0,s.jsxs)(t.p,{children:["However, forcing a custom anchor Item is also possible with the imported ",(0,s.jsx)(t.code,{children:"recommend"})," thanks to the ",(0,s.jsx)(t.code,{children:"overrideOnPageAnchor()"})," method (requiring ",(0,s.jsx)(t.code,{children:"itemId"})," and ",(0,s.jsx)(t.code,{children:"itemType"})," string arguments) that can be deployed both along with RecommendationsConfig as well as within the ",(0,s.jsxs)(t.a,{href:"/docs/interaction-studio/mcp-serverside-code-basics#writing-serverside-code",children:[(0,s.jsx)(t.code,{children:"run"})," block"]}),":"]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{9} title="Changing Item anchor for recommendation"',children:"import { RecommendationsConfig, recommend } from \"recs\";\n\nexport class customAnchorRecommendation implements CampaignTemplateComponent {\n // Renders interface for configuring the recommendation\n recsConfig: RecommendationsConfig = new RecommendationsConfig().restrictItemType(\"Product\");\n\n run(context: CampaignComponentContext) {\n // Replaces currently viewed Item anchor context with a custom one\n this.recsConfig.overrideOnPageAnchor('251422', 'Product');\n\n return {\n products: recommend(context, this.recsConfig),\n };\n }\n}\n"})})]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationsrecommendidsonly",children:"context.services.recommendations.recommendIdsOnly()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"recommendIdsOnly()"})," method works like ",(0,s.jsx)(t.a,{href:"#contextservicesrecommendationsrecommend",children:(0,s.jsx)(t.code,{children:"recommend()"})}),", but instead of returning an array of objects with Item details, it returns an array of Item IDs as strings. Just as ",(0,s.jsx)(t.code,{children:"recommendIdsOnly"})," you can import with ",(0,s.jsx)(t.code,{children:"RecommendationsConfig"})," from the ",(0,s.jsx)(t.code,{children:"recs"})," module."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{8} title="Return IDs of items recommended from a recipe"',children:"const recommendationsRequest = {\n currentItemId: '1017847',\n currentItemType: 'Product',\n maxResults: 12,\n recipeId: '7H5OK',\n userId: context.user.id\n}\nconst recommendedItemIds = context.services.recommendations.recommendIdsOnly(recommendationsRequest);\n"})}),"\n",(0,s.jsx)(t.p,{children:"It can be helpful if you only need to pass IDs to the e-commerce platform for it to render the campaign experience or when you want to filter out specific IDs returned by a recipe from another recommendation you deploy."}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationssmartsearch",children:"context.services.recommendations.smartSearch()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"smartSearch()"})," method allows you to get recommendations based on search query string (at least 3 characters long) and a recipe (for example, to recommend items when user interacts with a search box on the page):"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{7} title="Return Items recommended using smart search"',children:'const smartSearchRequest = {\n query: "jacket",\n maxResults: 1,\n recipeId: "7H5OK",\n userId: context.user.id\n}\nconst recommendedItems = context.services.recommendations.smartSearch(smartSearchRequest);\n'})}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"query"})," parameter is looking for a match in the name and description (only), then filters found Items using the provided Recipe ID. Keep in mind that the Recipe cannot be using Ingredients requiring an Item anchor. It\u2019s best to use the Any Items ingredient and then optionally sort it using ",(0,s.jsx)(t.a,{href:"#contextservicesrecommendationssmartsort",children:(0,s.jsx)(t.code,{children:"smartSort()"})}),"."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"smartSearch()"})," can return more than 12 recommendations (it can bring back thousand - and frequently it will need to so that there pool big enough for proper ",(0,s.jsx)(t.a,{href:"#contextservicesrecommendationssmartsort",children:(0,s.jsx)(t.code,{children:"smartSort()"})})," results), but as it returns whole Item details, it can impact performance. It might be helpful to filter the outcome just to the information required for your purpose for further processing."]}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Return only IDs of items recommended using smart search"',children:"const recommendedItemsIds = context.services.recommendations.smartSearch(smartSearchRequest).map(item => item.id);\n"})})]}),"\n",(0,s.jsx)(t.h4,{id:"contextservicesrecommendationssmartsort",children:"context.services.recommendations.smartSort()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"smartSort()"})," method requires an object with an ",(0,s.jsx)(t.code,{children:"itemIds"})," array, ",(0,s.jsx)(t.code,{children:"recipeId"}),", and ",(0,s.jsx)(t.code,{children:"userId"}),". It is a cool feature for the ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog"})})," set of functions as it can filter and order Item IDs pulled from a custom attribute or a catalog retrieve based on current user interest using a provided Recipe."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{7} title="Return items sorted using a Recipe"',children:"const itemsToBeSorted = ['1018913', '60365', '1017847', '1105'];\nconst smartSortRequest = {\n itemIds: itemsToBeSorted,\n recipeId: '7H5OK',\n userId: context.user.id\n}\nconst smartSortedItems = context.services.recommendations.smartSort(smartSortRequest);\n"})}),"\n",(0,s.jsx)(t.h3,{id:"servicessmarttrends",children:"services.smartTrends"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"smartTrends()"})," method lets you leverage the MCP Trends feature directly in the Serverside code of the Campaign. It requires a special ",(0,s.jsx)(t.code,{children:"SmartTrendsRequest"})," argument structure (",(0,s.jsx)(t.code,{children:"{itemIds: ['1018913'], itemType: \"Product\", lookbackMinutes: 9999 }"}),") and returns an array of objects with product engagement details within the provided lookback (",(0,s.jsx)(t.code,{children:"[{itemId: '1018913', visitViews: 1234, purchases: 98}]"}),")."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Return item engagement details"',children:"const smartTrendsRequest: SmartTrendsRequest = {\n itemIds: ['1018913'],\n itemType: 'Product',\n lookbackMinutes: 1656\n}\nconst smartTrendItemDetails = context.services.smartTrends.smartTrends(smartTrendsRequest);\n"})}),"\n",(0,s.jsxs)(t.p,{children:["It\u2019s a nice and more powerful alternative to the client-side code API approach based on the ",(0,s.jsx)(t.a,{href:"https://github.com/MateuszDabrowski/mcp-campaign-templates/tree/main/Global%20Templates/SalesforceInteractions/Trends",children:"Trends Global Template"}),"."]}),"\n",(0,s.jsx)(t.h3,{id:"servicessurveys",children:"services.surveys"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.surveys object"',children:'{\n "getSurey": (surveyId: string): Survey\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"servicesdecisions",children:"services.decisions"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.decisions object"',children:'{\n "decide": (request: ContextualBanditRequest): Item[]\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"servicescorvus",children:"services.corvus"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.corvus object"',children:'{\n "contextualBandit": {\n "decide": (request: ContextualBanditRequest, filter: PromotionFilter): Item[]\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"servicespromotioncatalog",children:"services.promotionCatalog"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.services.promotionCatalog object"',children:'{\n "findPromotions": (filter: ItemFilter, context: CampaignComponentContext): Promotion: [],\n "promotionFilter": (contentZone: string): PromotionFilter\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h2,{id:"user",children:"user"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user"})," is the most significant property, covering tons of information about the user that triggered the campaign. It contains multiple subobjects and methods perfect for statistics-based use cases within the serverside code."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user object"',children:'{\n "attributes": Object,\n "profileObjects": Object,\n "visits": [Object],\n "orderHistory": [Object],\n "location": Object,\n "currentCart": Object,\n "anonymous": boolean,\n "segmentMembership": [Object],\n "id": string,\n actionCount: (request: ActionStatsRequest): number,\n actionCountPerItem: (request: ActionStatsRequest): Object,\n getDimensionActivity: (dimension: string, start: Date, end: Date): {\n [itemId: string]: ItemActionStats\n },\n getDimensionActivityByDay: (dimension: string, start: Date, end: Date): {\n [date: string] : ItemActionStats\n },\n getEmailSendHistory: (start: Date, end: Date): EmailSendActivity[] || (): EmailSendActivity[],\n getLatestOrderByStatus: (status: \'Open\' | \'Purchased\' | \'Cancelled\'): Order,\n getSegmentJoinDate: (segmentId: string): Date,\n itemStatTotal: (request: ItemStatsRequest): number,\n itemStatTotalPerItem: (request: ItemStatsRequest): ItemStat[],\n pageViewCount: (request: StatsRequest): number,\n visitCount: (request: StatsRequest): number,\n visitDurationMillis: (request: StatsRequest): number,\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Let's start our discovery of ",(0,s.jsx)(t.code,{children:"context.user"})," with the methods."]}),"\n",(0,s.jsx)(t.h3,{id:"user-methods",children:"user methods"}),"\n",(0,s.jsx)(t.h4,{id:"contextuseractioncount",children:"context.user.actionCount()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires an ActionStatsRequest (",(0,s.jsx)(t.code,{children:"{actionName: 'Name of the action'}"}),") and returns the total of provided action triggers for the current user. You can also extend ActionStatsRequest with ",(0,s.jsx)(t.code,{children:"start"})," or ",(0,s.jsx)(t.code,{children:"end"})," (but not both) date properties to limit the timeframe of the action count."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3} title="Check how many times customer viewed cart within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst homeViewCount = context.user.actionCount({actionName: 'Viewed Cart', start: yesterday}); // Returns: 4\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextuseractioncountperitem",children:"context.user.actionCountPerItem()"}),"\n",(0,s.jsxs)(t.p,{children:["In theory, it should be able to return the action count per item (after passing a ",(0,s.jsx)(t.code,{children:"'Viewed Product'"})," action in ActionStatsRequest, it should show the counts per each product where that action triggered). But it doesn't. It returns the same information as the ",(0,s.jsx)(t.a,{href:"#contextuseractioncount",children:(0,s.jsx)(t.code,{children:"actionCount()"})})," method, but instead of doing it directly as a number, it does it as an object with an action name. Unless I'm missing something, it's useless."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Full on promise, null on delivery actionCountPerItem method"',children:"const homeViewCount = context.user.actionCountPerItem({actionName: 'Viewed Product'}); // Returns: {'Viewed Product': 5}\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetdimensionactivity",children:"context.user.getDimensionActivity()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires a dimension (a Catalog, like ",(0,s.jsx)(t.code,{children:"'Product'"}),", '",(0,s.jsx)(t.code,{children:"Category"}),"' or ",(0,s.jsx)(t.code,{children:"'CustomCatalog'"}),") and start + end date boundaries. This time, you must always provide both in that exact order. The significant difference with this method is that you pass direct arguments, not a grouping Stat object. It returns an object with Item IDs and related activity data from the selected Dimension with which the user interacted during the timeframe."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3,5} title="Find the activity in a specified catalog"',children:'const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst brandActivity = context.user.getDimensionActivity(\'Brand\', yesterday, today); // Returns:\n// {\n// "Apple": {\n// "view": 2,\n// "viewOutOfStock": 0,\n// "viewDetail": 0,\n// "viewTime": 43339,\n// "cart": 1,\n// "cartValue": 215,\n// "purchase": 1,\n// "purchaseValue": 215,\n// "review": 0,\n// "share": 0,\n// "comment": 0,\n// "favorite": 0\n// }\n// }\n'})}),"\n",(0,s.jsx)(t.p,{children:"That's an excellent set of data to calculate the most viewed Category, longest viewed Product, or most purchased Brand by that specific user. Unfortunately, it's still just a proxy for the actual affinity data, which is unavailable."}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsxs)(t.p,{children:["While you can work on the returned object, you cannot directly pass it to the serverside payload. You can output the final value (f.e. ",(0,s.jsx)(t.code,{children:"brandActivity.Apple.view"}),"), but both ",(0,s.jsx)(t.code,{children:"brandActivity"})," and ",(0,s.jsx)(t.code,{children:"brandActivity.Apple"})," will break it."]}),(0,s.jsxs)(t.p,{children:["You can perform calculations in serverside code on any level, but if you need to output it directly in the payload, there is a trick: ",(0,s.jsx)(t.code,{children:"JSON.parse(JSON.strinify(brandActivity))"}),"."]})]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetdimensionactivitybyday",children:"context.user.getDimensionActivityByDay()"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"getDimensionActivityByDay"})," method works nearly the same as ",(0,s.jsx)(t.a,{href:"#contextusergetdimensionactivity",children:(0,s.jsx)(t.code,{children:"getDimensionActivity"})}),". There are two key differences:"]}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"It requires additional argument - right after selecting the Dimension, you must also pass the specific Item ID for which you want to see the activity."}),"\n",(0,s.jsx)(t.li,{children:"The returned Object will have epoch properties for each activity day within the selected period."}),"\n"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3,5} title="Find the activity in a specified catalog"',children:'const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst brandActivity = context.user.getDimensionActivityByDay(\'Brand\', \'Apple\', yesterday, today); // Returns:\n// {\n// "1707782400000": {\n// "view": 2,\n// "viewOutOfStock": 0,\n// "viewDetail": 0,\n// "viewTime": 43339,\n// "cart": 1,\n// "cartValue": 215,\n// "purchase": 1,\n// "purchaseValue": 215,\n// "review": 0,\n// "share": 0,\n// "comment": 0,\n// "favorite": 0\n// }\n// }\n'})}),"\n",(0,s.jsxs)(t.p,{children:["It also has the same payload limitation as ",(0,s.jsx)(t.a,{href:"#contextusergetdimensionactivity",children:(0,s.jsx)(t.code,{children:"getDimensionActivity"})}),", and the same workaround is available."]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetemailsendhistory",children:"context.user.getEmailSendHistory()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires either nothing or start/end data boundary and returns... nothing. At least I couldn't get it to work with the ",(0,s.jsx)(t.a,{href:"/docs/interaction-studio/mcp-open-time-email",children:"OTE Campaign"})," data. It may leverage the barely working ",(0,s.jsx)(t.a,{href:"../../../sites/ideas/mc-personalization-ideas#external-email-campaign-etl-send-segmentation",children:"External Email Campaign ETL"}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetlatestorderbystatus",children:"context.user.getLatestOrderByStatus()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires an order status (",(0,s.jsx)(t.code,{children:"'Open'"}),", ",(0,s.jsx)(t.code,{children:"'Purchased'"})," or ",(0,s.jsx)(t.code,{children:"'Cancelled'"}),") and returns the most recent Order object in the selected state. The data structure and content are the same as in the ",(0,s.jsx)(t.a,{href:"#userorderhistory",children:(0,s.jsx)(t.code,{children:"user.orderHistory"})}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contextusergetsegmentjoindate",children:"context.user.getSegmentJoinDate()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires Segment ID (you can view it in User Segments after you add the ID column or by opening a specific segment and copying five alphanumerical characters from URL: ",(0,s.jsx)(t.code,{children:".../segment/{SegmentID}/members..."}),") and returns an epoch with join date. It's a fantastic way to capture additional context for the user (f.e. how many days ago he joined the Gold Tier segment)."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'title="Segment join epoch fun"',children:"const segmentJoinEpoch = context.user.getSegmentJoinDate('qWeR1'); // Returns: 1695796858287\n"})}),"\n",(0,s.jsxs)(t.p,{children:["If the Segment ID is incorrect or the user has not joined the provided segment, it will return ",(0,s.jsx)(t.code,{children:"null"}),"."]}),"\n",(0,s.jsxs)(t.admonition,{title:"You Should Know",type:"note",children:[(0,s.jsx)(t.p,{children:"You can easily convert epoch to date to simplify date calculations:"}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{2,7} title="Perform date comparisons on epoch"',children:"const segmentJoinEpoch = context.user.getSegmentJoinDate('qWeR1'); // Returns: 1695796858287\nconst segmentJoinDate = new Date(segmentJoinEpoch);\n\nconst today = new Date();\nconst lastWeek = new Date(today.setDate(today.getDate() - 7));\n\nconst hasJoinedLastWeek = segmentJoinDate > lastWeek;\n"})})]}),"\n",(0,s.jsx)(t.h4,{id:"contextuseritemstattotal",children:"context.user.itemStatTotal()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires an ItemStatsRequest (",(0,s.jsx)(t.code,{children:"{itemType: 'CatalogName', statType: 'StatTypeName'}"}),") and returns the count for that stat for a given Catalog. You can also extend ItemStatsRequest with another optional property ",(0,s.jsx)(t.code,{children:"itemId: 'id'"})," to limit the result to a specific Item within a given Catalog (itemType). Finally, as with ",(0,s.jsx)(t.a,{href:"#contextuseractioncount",children:"actionCount()"}),", you can also use ",(0,s.jsx)(t.code,{children:"start"})," or ",(0,s.jsx)(t.code,{children:"end"})," timeframe boundaries - but not both."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-8} title="Time spent by the user on Laptop Category within the last day in milliseconds"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.itemStatTotal({\n itemId: 'Laptop',\n itemType: 'Category',\n statType: 'ViewTime',\n start: yesterday\n}); // Returns: 98663\n"})}),"\n",(0,s.jsx)(t.p,{children:"Available statTypes: 'View', 'ViewOutOfStock', 'ViewValue', 'ViewDetail', 'QuickView', 'ViewTime', 'Cart', 'CartValue', 'Purchase', 'Visit', 'PurchaseValue', 'Review', 'Share', 'Comment', 'Favorite', 'Searches', 'SearchClicks', 'ClickThrough', 'RemoveFromCart', 'RemoveFromCartValue', 'RecommendedCount', 'PageLoadTime', 'PageLoadTimeCount', 'DomLoadTime', 'DomLoadTimeCount', 'TwReceiverTime', 'TwReceiverTimeCount', 'NumErrorEvents', 'TriggeredCount', 'RequestedForServing', 'EligibleForServing', 'Served'."}),"\n",(0,s.jsx)(t.p,{children:"Remember that the meaning of the returned value will differ depending on the selected statType - it can be count, milliseconds or money."}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsxs)(t.p,{children:["This method works perfectly with the ",(0,s.jsx)(t.a,{href:"#contexteventitemid",children:(0,s.jsx)(t.code,{children:"context.event.itemId()"})})," and ",(0,s.jsx)(t.a,{href:"#contexteventitemtype",children:(0,s.jsx)(t.code,{children:"context.event.itemType()"})})," as with those, you can pull relevant stats for a currently viewed Item and adapt payload for it (f.e. adapt Exit Intent incentive based on the number of visits or time spent on currently viewed product)."]})}),"\n",(0,s.jsx)(t.h4,{id:"contextuseritemstattotalperitem",children:"context.user.itemStatTotalPerItem()"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"itemStatsPerItem()"})," works in a very similar manner to ",(0,s.jsx)(t.a,{href:"#contextuseritemstattotal",children:(0,s.jsx)(t.code,{children:"itemStatsTotal()"})})," and accepts the same ItemStatsRequest. The key difference is that instead of a single value, it will return an array of objects, each containing an itemId and value specific to that item."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-7} title="Time spent by the user on Products within the last day in milliseconds"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.itemStatPerItem({\n itemType: 'Product',\n statType: 'ViewTime',\n start: yesterday\n}); // Returns: [{itemId: '123', value: 9238}, {itemId: '456', value: 26651}]\n"})}),"\n",(0,s.jsxs)(t.p,{children:["While you can pass ",(0,s.jsx)(t.code,{children:"itemId: 'id'"})," in the ItemStatsRequest, it will limit the outputted array to a single object for that item, making it not useful vs ",(0,s.jsx)(t.a,{href:"#contextuseritemstattotal",children:(0,s.jsx)(t.code,{children:"itemStatsTotal()"})}),"."]}),"\n",(0,s.jsx)(t.h4,{id:"contextuserpageviewcount",children:"context.user.pageViewCount()"}),"\n",(0,s.jsxs)(t.p,{children:["Requires StatsRequest (",(0,s.jsx)(t.code,{children:"{start: Date, end: Date}"})," - use either start or end; using both will always return 0) and returns the count of pages viewed in that timeframe. Both timeframe bounds are required."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-6} title="Pages viewed within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.pageViewCount({\n start: yesterday\n}); // Returns: 9\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextuservisitcount",children:"context.user.visitCount()"}),"\n",(0,s.jsxs)(t.p,{children:["Similar to ",(0,s.jsx)(t.a,{href:"#contextuserpageviewcount",children:"pageViewCount()"}),", it requires StatsRequest (",(0,s.jsx)(t.code,{children:"{start: Date, end: Date}"})," - use either start or end; using both will always return 0) but returns the count of visits instead of specific pages."]}),"\n",(0,s.jsx)(t.admonition,{title:"You Should Know",type:"note",children:(0,s.jsx)(t.p,{children:"Visit for Marketing Cloud Personalization starts from the first page view and ends after the user reaches 30 minutes of inactivity on the site. So if a user goes to your website to view a few pages, leaves and then returns after 40 minutes - it will be counted as a separate visit."})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-6} title="Visits within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.visitCount({\n start: yesterday\n}); // Returns: 2\n"})}),"\n",(0,s.jsx)(t.h4,{id:"contextuservisitdurationmilis",children:"context.user.visitDurationMilis()"}),"\n",(0,s.jsxs)(t.p,{children:["Similar to ",(0,s.jsx)(t.a,{href:"#contextuserpageviewcount",children:"pageViewCount()"}),", it requires StatsRequest (",(0,s.jsx)(t.code,{children:"{start: Date, end: Date}"})," - use either start or end, using both will always return 0) but returns the number of milliseconds the user spent on your website in a specified timeframe."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-ts",metastring:'{3-6} title="Visits within the last day"',children:"const today = new Date();\nconst yesterday = new Date(today.setDate(today.getDate() - 1));\nconst itemViewTime = context.user.visitDurationMilis({\n start: yesterday,\n end: today\n}); // Returns: 98663\n"})}),"\n",(0,s.jsx)(t.h3,{id:"userattributes",children:"user.attributes"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.attributes"})," object contains out-of-the-box, custom and hidden attributes with respective values for the user. It's an instrumental part of the ",(0,s.jsx)(t.code,{children:"context"})," as it allows you to pull user-specific data not only from the triggering event (like it is also possible with ",(0,s.jsx)(t.a,{href:"#contexteventfieldscustomattribute",children:(0,s.jsx)(t.code,{children:"context.event.fields.customAttribute"})}),") but also from past events. This enables fun use cases like saving in custom attributes the last viewed Product and Category with Sitemap and then leveraging that information when the user is on the non-product page of your website to bring them back onto the funnel. It's also great to personalize your campaign (f.e. with the first name in the info banner or overlay)."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.attributes object"',children:'{\n "created": {\n "value": number // epoch\n },\n "customAttribute": {\n "value": any\n },\n "originatingReferrer": {\n "value": "{\\"medium\\":\\"Direct\\",\\"source\\":null,\\"terms\\":null,\\"domain\\":null,\\"subdomainReversed\\":null,\\"url\\":null,\\"landingUrl\\":\\"https://www.mateuszdabrowski.pl/\\"}"\n },\n "firstName": {\n "value": string\n },\n "lastViewedCartAt": {\n "value": number // epoch\n },\n "firstActivity": {\n "value": number // epoch\n }\n}\n'})}),"\n",(0,s.jsx)(t.h3,{id:"userprofileobjects",children:"user.profileObjects"}),"\n",(0,s.jsx)(t.p,{children:"\ud83d\udea7 Work in progress \ud83d\udea7"}),"\n",(0,s.jsx)(t.h3,{id:"uservisits",children:"user.visits"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.visits"})," is an Array with user visits. Remember that the Marketing Cloud Personalization visit starts from the first page view and ends after the user reaches 30 minutes of inactivity on the site. So if a user goes to your website to view a few pages, leaves and then returns after 40 minutes - it will be counted as a separate visit. It is critical - there is no way to access the history of each page the user visits. You can only see the visit (session start data) with a ",(0,s.jsx)(t.code,{children:"pageViewIndex"})," with a count of page views during that visit."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.visits array"',children:'[\n {\n "start": number, // epoch\n "lastEventTime": number, // epoch\n "timeSinceLastVisit": number, // milliseconds\n "referrer": { // || null\n "medium": "Direct",\n "source": null,\n "terms": null,\n "domain": null,\n "subdomainReversed": null,\n "url": null,\n "landingUrl": "https://www.mateuszdabrowski.pl/"\n },\n "deviceType": "Computer",\n "browser": "Chrome",\n "platform": "Web",\n "operatingSystem": "Windows",\n "weather": { // || null\n "temperature": 71,\n "humidity": 67,\n "windSpeed": 7,\n "rain3h": 0,\n "snow3h": 0,\n "cloudCoverage": 0,\n "condition": {\n "id": 800,\n "name": "clear sky",\n "icon": "01d",\n "category": "Clear"\n }\n },\n "pageViewIndex": 9\n }\n]\n'})}),"\n",(0,s.jsx)(t.p,{children:"While there are a few attributes here, I would like to focus on two that enable exciting use cases:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"referrer"})," can contain data of the website that led the user to you. If this is the case, you can create a dedicated campaign focusing on the source (f.e. small vouchers to convert people coming from voucher-gathering websites) or terms (f.e. changing the experience based on social ad terms passed)."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"weather"})," can provide you with details about temperature, rain and snow, unlocking like-magic use cases, f.e. if it is cold and showers for your customer, display a campaign with a dedicated message promoting a sunny and hot travel destination."]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"userorderhistory",children:"user.orderHistory"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.orderHistory"})," is an array with past orders in any status (open, purchased or cancelled) for the user. It contains everything - timeframes, order value and currency and even a list of all products in that order."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.orderHistory array"',children:'[\n {\n "id": null,\n "created": number, // epoch\n "updated": number, // epoch\n "purchaseDate": null,\n "visitAgeAtPurchase": number, // milliseconds\n "totalValue": number,\n "totalValueCurrency": null,\n "status": "Open",\n "metadata": null,\n "lineItems": [\n {\n "quantity": number,\n "price": number,\n "itemId": string,\n "attributes": {}\n },\n ],\n "attributes": {}\n }\n]\n'})}),"\n",(0,s.jsx)(t.h3,{id:"userlocation",children:"user.location"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.location"})," can be magic or trash - depending on the Internet Service Providers of your audience. The rule of thumb is good data for B2B and mixed data for B2C. It's worth checking because if you can trust/clean this data, you can do astounding things with it."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.location object"',children:'{\n "geographicPoint": {\n "latitude": number,\n "longitude": number\n },\n "timeZoneId": "Europe/Warsaw",\n "continentKey": "EU",\n "countryCode": "PL",\n "countryNumericCode": 616,\n "stateProvinceCode": "14",\n "city": "Warsaw",\n "postalCode": "00-633",\n "organization": "Pwc Polska Sp. Z O.o.",\n "naicsCode": "517311"\n}\n'})}),"\n",(0,s.jsxs)(t.p,{children:["Firstly, ",(0,s.jsx)(t.code,{children:"context.user.location.geographicPoint"})," contains latitude and longitude that can be perfect for ",(0,s.jsx)(t.a,{href:"#servicescatalog",children:(0,s.jsx)(t.code,{children:"context.services.catalog.findClosestItems()"})})," call."]}),"\n",(0,s.jsxs)(t.p,{children:["Secondly, if you target B2B customers and get organisation details (the example above is real - it returned all those details when I checked it from the PwC Poland office), it can help you get precious information about your known ",(0,s.jsx)(t.strong,{children:"and anonymous"})," visitors! However, a (big) grain of salt is needed - the NAICS Code (2017 NAICS Definition) returned for me Wired Telecommunications Carriers, which looks like code for Internet Services Provider, not PwC. For B2C, the ",(0,s.jsx)(t.code,{children:"organisation"})," field will return the Internet Service Provider name in most cases."]}),"\n",(0,s.jsx)(t.h3,{id:"usercurrentcart",children:"user.currentCart"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.currentCart"})," is a single object with the same structure as each of the orders stored in ",(0,s.jsx)(t.a,{href:"#userorderhistory",children:(0,s.jsx)(t.code,{children:"context.user.orderHistory"})}),". But because it is still a cart, not an order, most fields will be ",(0,s.jsx)(t.code,{children:"null"}),"/",(0,s.jsx)(t.code,{children:"0"}),"."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.currentCart object"',children:'{\n "id": null,\n "created": number, // epoch\n "updated": number, // epoch\n "purchaseDate": null,\n "visitAgeAtPurchase": 0,\n "totalValue": 0,\n "totalValueCurrency": null,\n "status": "Open",\n "metadata": null,\n "lineItems": [\n {\n "quantity": number,\n "price": number,\n "itemId": string,\n "attributes": {}\n },\n ],\n "attributes": {}\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"The fun use case here is checking when the user updated the cart and, if enough time has passed, leveraging the lineItems to deploy an abandoned basket Web Campaign."}),"\n",(0,s.jsx)(t.h3,{id:"usersegmentmembership",children:"user.segmentMembership"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"context.user.segmentMembership"})," is an array with segments the user is a member of. With a good segmentation naming convention, the ",(0,s.jsx)(t.code,{children:"segmentName"})," and ",(0,s.jsx)(t.code,{children:"joined"})," can capture valuable additional context for the user (f.e. how many days ago he joined the Gold Tier segment or became an at-risk customer)."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-js",metastring:'title="Structure of the context.user.segmentMembership array"',children:'[\n {\n "segmentId": string,\n "segmentName": string,\n "joined": number, // epoch\n "createIfMissing": boolean,\n "removal": boolean,\n "userId": string,\n "customerId": string,\n "customerType": "User"\n }\n]\n'})}),"\n",(0,s.jsx)(t.h2,{id:"accountid--datasetid",children:"accountId & datasetId"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"accountId"})," and ",(0,s.jsx)(t.code,{children:"datasetId"})," are string properties that contain information about the Marketing Cloud Personalization account and dataset that generated the event. It is only handy if you want environment-aware debug log visibility logic."]}),"\n",(0,s.jsx)(t.h2,{id:"configuration",children:"configuration"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"configuration"})," object property contains information about the campaign properties (fields you expect the marketer to fill in when configuring the campaign) in the experience for a given user. Not really useful, as in the serverside code, you can access the same information using the ",(0,s.jsx)(t.code,{children:"this"})," keyword (f.e. ",(0,s.jsx)(t.code,{children:"this.campaignPropertyName"}),")."]})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},6748:(e,t,n)=>{n.d(t,{U:()=>r});const s="leadText_qzwo";var i=n(4848);const r=e=>{let{content:t}=e;return(0,i.jsx)(i.Fragment,{children:(0,i.jsx)("p",{id:s,children:t})})}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const i={},r=s.createContext(i);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ecbe7f2c.f5c6d415.js b/assets/js/ecbe7f2c.873d88e4.js similarity index 96% rename from assets/js/ecbe7f2c.f5c6d415.js rename to assets/js/ecbe7f2c.873d88e4.js index c8d3aeb4c..6c975190f 100644 --- a/assets/js/ecbe7f2c.f5c6d415.js +++ b/assets/js/ecbe7f2c.873d88e4.js @@ -1 +1 @@ -"use strict";(self.webpackChunkmd=self.webpackChunkmd||[]).push([[5718],{7674:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>t,default:()=>m,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=s(4848),a=s(8453),l=s(6748);const r={id:"sfmc-sql-style-guide",title:"SFMC SQL Style Guide",sidebar_label:"Style Guide",description:"Query with style. Readable, bug-free code is a few shifts & spaces away.",image:"img/og/og-image-sql-style-guide.png",tags:["Marketing Cloud","SQL","Style Guide","Best Practice"]},t=void 0,o={id:"sql/sfmc-sql-style-guide",title:"SFMC SQL Style Guide",description:"Query with style. Readable, bug-free code is a few shifts & spaces away.",source:"@site/docs/sql/sfmc-sql-style-guide.mdx",sourceDirName:"sql",slug:"/sql/sfmc-sql-style-guide",permalink:"/docs/sql/sfmc-sql-style-guide",draft:!1,unlisted:!1,editUrl:"https://github.com/MateuszDabrowski/mateuszdabrowski.pl/edit/master/docs/sql/sfmc-sql-style-guide.mdx",tags:[{inline:!0,label:"Marketing Cloud",permalink:"/docs/tags/marketing-cloud"},{inline:!0,label:"SQL",permalink:"/docs/tags/sql"},{inline:!0,label:"Style Guide",permalink:"/docs/tags/style-guide"},{inline:!0,label:"Best Practice",permalink:"/docs/tags/best-practice"}],version:"current",lastUpdatedBy:"Mateusz D\u0105browski",lastUpdatedAt:1641649742e3,frontMatter:{id:"sfmc-sql-style-guide",title:"SFMC SQL Style Guide",sidebar_label:"Style Guide",description:"Query with style. Readable, bug-free code is a few shifts & spaces away.",image:"img/og/og-image-sql-style-guide.png",tags:["Marketing Cloud","SQL","Style Guide","Best Practice"]},sidebar:"docs",previous:{title:"Null Functions",permalink:"/docs/sql/sfmc-sql-null-functions"},next:{title:"\u203a SQL Snippets",permalink:"/docs/category/-sql-snippets"}},c={},d=[{value:"Letter Case",id:"letter-case",level:2},{value:"SQL Syntax Case",id:"sql-syntax-case",level:3},{value:"Column & Table Names Case",id:"column--table-names-case",level:3},{value:"Alignment and Indentation",id:"alignment-and-indentation",level:2},{value:"Single Information per Line",id:"single-information-per-line",level:3},{value:"Left Aligned Keywords",id:"left-aligned-keywords",level:3},{value:"Consistent Indentation",id:"consistent-indentation",level:3},{value:"Intentional Spacing",id:"intentional-spacing",level:3},{value:"Commas Placement",id:"commas-placement",level:3},{value:"Explicit vs Implicit",id:"explicit-vs-implicit",level:2},{value:"Date Parts",id:"date-parts",level:3},{value:"JOIN and ON",id:"join-and-on",level:3},{value:"Table Aliases",id:"table-aliases",level:3},{value:"Not Equal To Symbol",id:"not-equal-to-symbol",level:3},{value:"Meaningful Column Names",id:"meaningful-column-names",level:3},{value:"Sum Up",id:"sum-up",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(l.U,{content:"Query with style. Readable, bug-free code is a few shifts & spaces away."}),"\n",(0,i.jsx)(n.p,{children:"First things first: this Salesforce Marketing Cloud SQL style guide is highly subjective. You may use it as it is, implement only some parts of it, or ignore it altogether. There are only two rules that I believe are a must-have:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Be consistent across your codebase."}),"\n",(0,i.jsx)(n.li,{children:"Strive for good readability."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Everything else is preference. And you are just about to learn about mine."}),"\n",(0,i.jsx)(n.h2,{id:"letter-case",children:"Letter Case"}),"\n",(0,i.jsx)(n.p,{children:"SQL gives you much freedom regarding the type of letter case you will be using for parts of your query. Let's use this freedom to create queries that are readable and aligned in convention to other Marketing Cloud programmatic languages operating on the same data."}),"\n",(0,i.jsx)(n.h3,{id:"sql-syntax-case",children:"SQL Syntax Case"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.code,{children:"UPPERCASE"})," for all elements of SQL syntax."]})}),"\n",(0,i.jsx)(n.p,{children:"This approach helps visually differentiate query language from Tables (data extensions, data views) and Columns (fields) to improve readability."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Upper Case for SQL Syntax */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n\n/* \u274c Pascal Case for SQL Syntax */\nSelect\n SubscriberKey\n , EmailAddress\nFrom Ent._Subscribers\nWhere DateJoined >= DateAdd(Month, -1, GetDate())\n\n/* \u274c Lower Case for SQL Syntax */\nselect\n SubscriberKey\n , EmailAddress\nfrom Ent._Subscribers\nwhere DateJoined >= dateadd(month, -1, getdate())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"column--table-names-case",children:"Column & Table Names Case"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.code,{children:"PascalCase"})," for all Table and Column names."]})}),"\n",(0,i.jsx)(n.p,{children:"Treat it as a soft recommendation, as it is highly connected to your organisation's conventions. If other connected systems are using a different style, it might be best to follow it in Marketing Cloud."}),"\n",(0,i.jsx)(n.p,{children:"It is especially true for Tables, as you might be using mixed convention leveraging lowercase, uppercase and underscores for Data Extension names. However, try not to use hyphens, as those will require you to use square brackets around the name and might interfere in query syntax highlighting, leading to worse readability."}),"\n",(0,i.jsxs)(n.p,{children:["The most popular SQL convention for Table and Column names is ",(0,i.jsx)(n.code,{children:"snake_case"}),". However, in Marketing Cloud, the Table and Column names will share the case between your queries and the User Interface. It is essential to make them as readable and human friendly as possible. Additionally, in many cases, you will also leverage those names in AMPScript and SSJS."]}),"\n",(0,i.jsxs)(n.p,{children:["Due to the above, I believe ",(0,i.jsx)(n.code,{children:"PascalCase"})," - especially for Column names - is the best choice for Marketing Cloud SQL."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Pascal Case for Table and Column names */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u2705 Pascal Case for Column names and custom consistent covention for Table names */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WEL_WelcomeCampaignSegment_20201011_OTH AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u274c Lower Case for Table and Column names */\nSELECT\n wel.subscriberkey\n , wel.emailaddress\n , o.eventdate AS opendate\nFROM welcomecampaignsegment AS wel\n INNER JOIN _open AS o\n ON o.subscriberkey = wel.subscriberkey\n\n/* \u274c Upper Case for Table and Column names */\nSELECT\n WEL.SUBSCRIBERKEY\n , WEL.EMAILADDRESS\n , O.EVENTDATE AS OPENDATE\nFROM WELCOMECAMPAIGNSEGMENT AS WEL\n INNER JOIN _OPEN AS O\n ON O.SUBSCRIBERKEY = WEL.SUBSCRIBERKEY\n"})}),"\n",(0,i.jsxs)(n.admonition,{title:"You Should Know",type:"note",children:[(0,i.jsx)(n.p,{children:"If you want to make your Style Guide even safer, you can decide on writing all Columns and Table names in square brackets. As Marketing Cloud is not checking whether you use SQL's reserved keywords, this approach will protect you from potential silent issue. The cost, however, is much more characters and less readable queries."}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:'title="You need to decide how hard you want to leverage the square brackets"',children:"SELECT\n [wel].[SubscriberKey]\n , [wel].[EmailAddress]\n , [o].[EventDate] AS [OpenDate]\nFROM [WelcomeCampaignSegment] AS [wel]\n INNER JOIN [_Open] AS [o]\n ON [o].[SubscriberKey] = [wel].[SubscriberKey]\n"})})]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h2,{id:"alignment-and-indentation",children:"Alignment and Indentation"}),"\n",(0,i.jsx)(n.p,{children:"SQL is very flexible when it comes to alignment and indentation of the query. Writing everything in one line creates a valid code that will run. But just because it is correct, it doesn't mean it is good. Generous use of new lines and indents has close to no impact on performance but a massive impact on readability. Enter and Space keys are your friends."}),"\n",(0,i.jsx)(n.p,{children:"There are many styles out there, and I decided to follow those that merge good writing speed with excellent readability."}),"\n",(0,i.jsx)(n.h3,{id:"single-information-per-line",children:"Single Information per Line"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Limit information per line to one."})}),"\n",(0,i.jsx)(n.p,{children:"I recommend keeping one information per line, as it allows for much easier scanning. The four most important examples of this approach are:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})})," Column in a separate line"]}),"\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where",children:(0,i.jsx)(n.code,{children:"WHERE"})})," condition in a separate line"]}),"\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})})," condition in a separate line"]}),"\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," and ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})})," relationship in a separate line"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Single information per line */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n ELSE 0\n END\n\n/* \u274c Multiple pieces of information per line */\nSELECT s.SubscriberKey AS SubscriberKey, j.EmailName AS EmailName, s.EventDate AS SentDate, j.DeliveredTime AS DeliveryDate, o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j ON j.JobID = s.JobID\n LEFT JOIN _Open AS o ON o.JobID = s.JobID AND o.ListID = s.ListID AND o.BatchID = s.BatchID AND o.SubscriberID = s.SubscriberID AND o.IsUnique = 1\nWHERE 1 = CASE WHEN j.EmailName LIKE 'UPS_%' THEN 1 WHEN j.EmailName LIKE 'CRS_%' THEN 1 ELSE 0 END\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As you can see, the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})})," and ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where",children:(0,i.jsx)(n.code,{children:"WHERE"})})," keywords have their separate line to mark respective block starting. For readability reasons, I make an exception if there is only one Column or condition to be used:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Single Column in SELECT and single condition in WHERE lines */\nSELECT SubscriberKey\nFROM _Subscribers\nWHERE Domain = 'mateuszdabrowski.pl'\n\n/* \u274c Separate lines with single SELECT Column and WHERE condition */\nSELECT\n SubscriberKey\nFROM _Subscribers\nWHERE\n Domain = 'mateuszdabrowski.pl'\n"})}),"\n",(0,i.jsxs)(n.admonition,{title:"You Should Know",type:"note",children:[(0,i.jsxs)(n.p,{children:["If you are using ",(0,i.jsx)(n.code,{children:"DISTINCT"})," or ",(0,i.jsx)(n.code,{children:"TOP"}),", put it into the same line as ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})}),". In such a case, even if you work on a single Column, move it to a separate row for better readability."]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Single Column in SELECT and single condition in WHERE lines */\nSELECT DISTINCT TOP 10\n SubscriberKey\nFROM ContenstSubmissions\n\n/* \u274c Separate lines for single SELECT Column and WHERE condition */\nSELECT DISTINCT TOP 10 SubscriberKey\nFROM ContenstSubmissions\n"})})]}),"\n",(0,i.jsx)(n.h3,{id:"left-aligned-keywords",children:"Left Aligned Keywords"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Align main SQL keywords to the left."})}),"\n",(0,i.jsx)(n.p,{children:"This rule focuses on writing speed. While I prefer the Vertically Aligned Space approach's aesthetics, I don't see any significant readability gains. On the other hand, writing in this style in Marketing Cloud is a pain, as there is no autoformatter supporting it in the Query Studio or Query Activity. We would have to add all those additional spaces manually. It's just not worth it."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Left Aligned Keywords */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n\n/* \u274c Post Keyword Space Aligned Vertically */\nSELECT SubscriberKey,\n EmailAddress\n FROM Ent._Subscribers\n WHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"consistent-indentation",children:"Consistent Indentation"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use indentation to highlight SQL keyword relationships."})}),"\n",(0,i.jsx)(n.p,{children:"This rule focuses on readability. The logic, in short, is to indent whenever the line is dependent on the previous line (child line), for example:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Selected Column Names are children of ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," keywords are children of the initial Table referenced with ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-from",children:(0,i.jsx)(n.code,{children:"FROM"})})]}),"\n",(0,i.jsxs)(n.li,{children:["Joining relationships (",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})}),") are children of ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})]}),"\n",(0,i.jsxs)(n.li,{children:["Case conditions are children of the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})})]}),"\n",(0,i.jsxs)(n.li,{children:["Where conditions are children of the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where",children:(0,i.jsx)(n.code,{children:"WHERE"})})]}),"\n",(0,i.jsx)(n.li,{children:"Sub-queries follow the same rules in respective indentation level."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"For simplicity I use 4-spaces indent, as it is both standard and can be added in Marketing Cloud Query with a single click of the Tab key."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Dependency based indentation */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n ELSE 0\n END\n\n/* \u274c Lack of indentation */\nSELECT\ns.SubscriberKey AS SubscriberKey\n, j.EmailName AS EmailName\n, s.EventDate AS SentDate\n, j.DeliveredTime AS DeliveryDate\n, o.EventDate AS OpenDate\nFROM _Sent AS s\nLEFT JOIN _Job AS j ON j.JobID = s.JobID\nLEFT JOIN _Open AS o ON o.JobID = s.JobID\nAND o.ListID = s.ListID\nAND o.BatchID = s.BatchID\nAND o.SubscriberID = s.SubscriberID\nAND o.IsUnique = 1\nWHERE 1 = CASE\nWHEN j.EmailName LIKE 'UPS_%' THEN 1\nWHEN j.EmailName LIKE 'CRS_%' THEN 1\nELSE 0\nEND\n"})}),"\n",(0,i.jsx)(n.h3,{id:"intentional-spacing",children:"Intentional Spacing"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use spaces wherever it makes the query more readable."})}),"\n",(0,i.jsxs)(n.p,{children:["The must-have is spacing around any ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where#basic-operators",children:"operators"})," (equality or comparison) and after commas."]}),"\n",(0,i.jsxs)(n.p,{children:["However, there is another place where spacing is beneficial for readability but might require an exception in some scenarios. Spacing for ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select#aliasing-with-as",children:"aliases"})," and ",(0,i.jsx)(n.code,{children:"THEN"})," keywords of the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})})," statement."]}),"\n",(0,i.jsxs)(n.p,{children:["I try to use it whenever possible, but when there is huge imbalance in length (for example one Column requires multi-function calculation or there is a single complex ",(0,i.jsx)(n.code,{children:"WHEN"})," in ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})}),") equal spacing might make the query harder to read. Always decide which approach works best for your query from readability perspective."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Spacing around operators plus equalizing aliases and THEN */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n WHEN j.EmailName = 'OTH_SeedList' THEN 1\n ELSE 0\n END\n\n/* \u2705 Spacing around operators plus equalizing aliases with exceptions */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\n , DATEDIFF(HOUR, s.EventDate, o.EventDate) AS TimeToOpen\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' OR j.EmailName LIKE 'CRS_%' THEN 1\n WHEN j.EmailName = 'OTH_SeedList' THEN 1\n ELSE 0\n END\n\n/* \u274c Lack of spacing */\nSELECT\n s.SubscriberKey AS SubscriberKey\n ,j.EmailName AS EmailName\n ,s.EventDate AS SentDate\n ,j.DeliveredTime AS DeliveryDate\n ,o.EventDate AS OpenDate\n ,DATEDIFF(HOUR,s.EventDate,o.EventDate) AS TimeToOpen\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID=s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID=s.JobID\n AND o.ListID=s.ListID\n AND o.BatchID=s.BatchID\n AND o.SubscriberID=s.SubscriberID\n AND o.IsUnique=1\nWHERE\n 1=CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n WHEN j.EmailName='OTH_SeedList' THEN 1\n ELSE 0\n END\n"})}),"\n",(0,i.jsx)(n.h3,{id:"commas-placement",children:"Commas Placement"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use commas at the beginning of the line."})}),"\n",(0,i.jsx)(n.p,{children:"There are few approaches related to comma placement. Initially, I favoured commas at the end of the line, as I found them more accessible to use due to their similarity to natural language. However, there are strong reasons to use the comma at the beginning of the line. Here is what convinced me to change my style:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Adding or deleting a Column requires a change in only one line. It's easier, faster and minimises the risk of a crash due to the trailing comma."}),"\n",(0,i.jsx)(n.li,{children:"Above is also very beneficial during difference checking and when leveraging git for query version control. With a comma at the beginning of the line, the Column addition or deletion is displayed correctly as a single line change."}),"\n",(0,i.jsxs)(n.li,{children:["Having a comma in the beginning makes it easier to assess where a new Column definition starts quickly. It is a vast readability improvement when you are using more complex structures, like ",(0,i.jsxs)(n.a,{href:"/docs/sql/sfmc-sql-case#conditional-values-with-case",children:[(0,i.jsx)(n.code,{children:"CASE"})," in ",(0,i.jsx)(n.code,{children:"SELECT"})]}),"."]}),"\n",(0,i.jsx)(n.li,{children:"It's also easier to quickly assess whether you have a comma for each Column. With lines of various length, it is much harder with the comma at the end."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For the sake of readability, I indent the first Column by two spaces so that it is in line with the following ones. Similarly, I indent ",(0,i.jsx)(n.code,{children:"END"})," after ",(0,i.jsxs)(n.a,{href:"/docs/sql/sfmc-sql-case#conditional-values-with-case",children:[(0,i.jsx)(n.code,{children:"CASE"})," in ",(0,i.jsx)(n.code,{children:"SELECT"})]})," by two spaces for the same reason."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{3-5,10-12}",children:"/* \u2705 Commas at the beginning */\nSELECT\n SubscriberKey\n , EmailAddress\n , DateJoined\nFROM Ent._Subscribers\n\n/* \u274c Commas in the end */\nSELECT\n SubscriberKey,\n EmailAddress,\n DateJoined\nFROM Ent._Subscribers\n"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h2,{id:"explicit-vs-implicit",children:"Explicit vs Implicit"}),"\n",(0,i.jsx)(n.p,{children:"Many things in SQL can be done in multiple ways - using various functions, symbols or shortcuts. While all those options may work, not all are a good idea. Whenever you are choosing the approach, go for the explicit and straightforward. Even if it means writing a few characters more."}),"\n",(0,i.jsx)(n.h3,{id:"date-parts",children:"Date Parts"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use full ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-date-functions#date-parts",children:"Date Parts"})," names."]})}),"\n",(0,i.jsx)(n.p,{children:"Yes, abbreviations let you save few characters, but they kill the readability unless someone is fluent in those shortcuts. For Marketing Cloud purposes, the time saved during writing is not worth the time lost when reading. Go with the full version."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{6,13}",children:"/* \u2705 Full Date Part */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n\n/* \u274c Abbreviated Date Part */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(M, -1, GETDATE())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"join-and-on",children:"JOIN and ON"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"INNER JOIN"})})," name and reference Column from the new Table first after ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Instead of just ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})}),", write ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#inner-join",children:(0,i.jsx)(n.code,{children:"INNER JOIN"})})," - it's longer but explicit and in line with the rest of ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," keywords. It makes it easier to scan queries with ",(0,i.jsxs)(n.a,{href:"/docs/sql/sfmc-sql-join#multiple-various-joins",children:["multiple various ",(0,i.jsx)(n.code,{children:"JOIN"})]})," statements."]}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, when defining ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," relationships after ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})}),", firstly reference the Column from the joined Table. The previous Table should be on the right side. It will improve consistency and reading speed."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{7-8,16-17}",children:"/* \u2705 Explicit Inner Join and Column from new Table on the left side of the ON condition */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u274c Implicit Inner Join and Column from new Table on the right side of the ON condition */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n JOIN _Open AS o\n ON wel.SubscriberKey = o.SubscriberKey\n"})}),"\n",(0,i.jsx)(n.h3,{id:"table-aliases",children:"Table Aliases"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["When using ",(0,i.jsx)(n.code,{children:"JOIN"}),", add meaningful aliases for Tables and prefix all Columns with them."]})}),"\n",(0,i.jsx)(n.p,{children:"There are a few points:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["If you are working on only one Table without ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," - don't use ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#table-name-prefix",children:"aliases"})," at all. They are not needed and would make the query less readable."]}),"\n",(0,i.jsxs)(n.li,{children:["If you have any ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," - always use ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#table-name-prefix",children:"aliases and prefixes"}),". SQL doesn't always require it, but it is much easier to read the query when the Columns have an explicit Table mention in the prefix."]}),"\n",(0,i.jsx)(n.li,{children:"When you create an alias for a Table, make it meaningful. Using subsequent letters of the alphabet is not a good idea. Instead, use something that will remind the reader of the full name - for example, abbreviation using the first letter of each word in the Table. It will allow for much easier reading."}),"\n",(0,i.jsxs)(n.li,{children:["Always use ",(0,i.jsx)(n.code,{children:"AS"})," keyword between the Table name and the alias."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 No aliasing in single Table query */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\n\n/* \u274c Aliasing in single Table query */\nSELECT\n s.SubscriberKey\n , s.EmailAddress\nFROM Ent._Subscribers AS s\n\n/* \u2705 Meaningful aliasing and prefixes in multi Table query */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u274c No aliasing and no prefix in multi Table query */\nSELECT\n SubscriberKey\n , EmailAddress\n , EventDate AS OpenDate\nFROM WelcomeCampaignSegment\n INNER JOIN _Open\n ON _Open.SubscriberKey = WelcomeCampaignSegment.SubscriberKey\n\n/* \u274c Not meaningful aliasing and no AS keyword in multi Table query */\nSELECT\n a.SubscriberKey\n , a.EmailAddress\n , b.EventDate AS OpenDate\nFROM WelcomeCampaignSegment a\n INNER JOIN _Open b\n ON a.SubscriberKey = b.SubscriberKey\n"})}),"\n",(0,i.jsx)(n.h3,{id:"not-equal-to-symbol",children:"Not Equal To Symbol"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.code,{children:"!="})," instead of ",(0,i.jsx)(n.code,{children:"<>"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"!="})," symbol is much more popular and used in many languages. Using it makes the query more readable to people not experienced in SQL."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{4,9}",children:"/* \u2705 Use of != for negation */\nSELECT SubscriberKey\nFROM Ent._Subscribers\nWHERE CONVERT(DATE, DateJoined) != CONVERT(DATE, GETDATE())\n\n/* \u274c Use of <> for negation */\nSELECT SubscriberKey\nFROM Ent._Subscribers\nWHERE CONVERT(DATE, DateJoined) <> CONVERT(DATE, GETDATE())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"meaningful-column-names",children:"Meaningful Column Names"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use Column names that suggest the data type."})}),"\n",(0,i.jsx)(n.p,{children:"Just as with a letter case, you might have your hands tied by cross-system dependencies. But whenever possible, strive for meaningful names:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Use descriptive Column names. It is better to have a long explicit one (",(0,i.jsx)(n.code,{children:"IsTrackingSuppressed"}),") than a short mysterious abbreviation (",(0,i.jsx)(n.code,{children:"trk"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:["When the Column is a boolean, prefix it with ",(0,i.jsx)(n.code,{children:"Is"})," (or ",(0,i.jsx)(n.code,{children:"Has"}),"/",(0,i.jsx)(n.code,{children:"Does"})," depending on the underlying data)."]}),"\n",(0,i.jsxs)(n.li,{children:["When the Column is a date, suffix it with ",(0,i.jsx)(n.code,{children:"Date"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{3-8,17-22}",children:"/* \u2705 Meaningful and consistent Column Names */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\n , j.SuppressTracking AS IsTrackingSuppressed\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n\n/* \u274c No consistency and type alignment in Column Names */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryTime\n , o.EventDate AS OpenedAt\n , j.SuppressTracking AS SuppressTracking\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n"})}),"\n",(0,i.jsx)(n.h2,{id:"sum-up",children:"Sum Up"}),"\n",(0,i.jsx)(n.p,{children:"It is a long article, so let's gather all the recommendations in one place:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Be consistent"}),"\n",(0,i.jsx)(n.li,{children:"Strive for readability"}),"\n",(0,i.jsx)(n.li,{children:"Use comments to provide required context to your query"}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"UPPERCASE"})," for SQL syntax ",(0,i.jsx)(n.a,{href:"#sql-syntax-case",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"PascalCase"})," for Table & Column names ",(0,i.jsx)(n.a,{href:"#column--table-names-case",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Limit information per line to one ",(0,i.jsx)(n.a,{href:"#single-information-per-line",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Align main SQL keywords to the left ",(0,i.jsx)(n.a,{href:"#left-aligned-keywords",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use indentation to highlight the relationship between SQL keywords ",(0,i.jsx)(n.a,{href:"#consistent-indentation",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use spaces wherever it makes the query more readable ",(0,i.jsx)(n.a,{href:"#intentional-spacing",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use commas at the beginning of the line ",(0,i.jsx)(n.a,{href:"#commas-placement",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use full Date Parts names ",(0,i.jsx)(n.a,{href:"#date-parts",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"INNER JOIN"})," name over ",(0,i.jsx)(n.code,{children:"JOIN"})," ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["In ",(0,i.jsx)(n.code,{children:"JOIN ON"})," reference Column from newly joined Table on the left ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["When using ",(0,i.jsx)(n.code,{children:"JOIN"}),", add meaningful aliases for Tables and prefix all Columns ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Always use ",(0,i.jsx)(n.code,{children:"AS"})," keyword between the Table name and the alias ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"!="})," instead of ",(0,i.jsx)(n.code,{children:"<>"})," ",(0,i.jsx)(n.a,{href:"#not-equal-to-symbol",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use Column names that suggest the data type ",(0,i.jsx)(n.a,{href:"#meaningful-column-names",children:"\ud83d\udd17"})]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you want to share something I'm missing or have arguments for a different recommendation - ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/mateusz-dabrowski-marketing/",children:"let me know"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Looking for more Marketing Cloud style? Check out my:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/ssjs/ssjs-style-guide",children:"SSJS Style Guide"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/ampscript/ampscript-style-guide",children:"AMPScript Style Guide"})}),"\n"]})]})}function m(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},6748:(e,n,s)=>{s.d(n,{U:()=>l});const i="leadText_qzwo";var a=s(4848);const l=e=>{let{content:n}=e;return(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{id:i,children:n})})}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>t});var i=s(6540);const a={},l=i.createContext(a);function r(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkmd=self.webpackChunkmd||[]).push([[5718],{7674:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>t,default:()=>m,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=s(4848),a=s(8453),l=s(6748);const r={id:"sfmc-sql-style-guide",title:"SFMC SQL Style Guide",sidebar_label:"Style Guide",description:"Query with style. Readable, bug-free code is a few shifts & spaces away.",image:"img/og/og-image-sql-style-guide.png",tags:["Marketing Cloud","SQL","Style Guide","Best Practice"]},t=void 0,o={id:"sql/sfmc-sql-style-guide",title:"SFMC SQL Style Guide",description:"Query with style. Readable, bug-free code is a few shifts & spaces away.",source:"@site/docs/sql/sfmc-sql-style-guide.mdx",sourceDirName:"sql",slug:"/sql/sfmc-sql-style-guide",permalink:"/docs/sql/sfmc-sql-style-guide",draft:!1,unlisted:!1,editUrl:"https://github.com/MateuszDabrowski/mateuszdabrowski.pl/edit/master/docs/sql/sfmc-sql-style-guide.mdx",tags:[{inline:!0,label:"Marketing Cloud",permalink:"/docs/tags/marketing-cloud"},{inline:!0,label:"SQL",permalink:"/docs/tags/sql"},{inline:!0,label:"Style Guide",permalink:"/docs/tags/style-guide"},{inline:!0,label:"Best Practice",permalink:"/docs/tags/best-practice"}],version:"current",lastUpdatedBy:"Mateusz D\u0105browski",lastUpdatedAt:1729543696e3,frontMatter:{id:"sfmc-sql-style-guide",title:"SFMC SQL Style Guide",sidebar_label:"Style Guide",description:"Query with style. Readable, bug-free code is a few shifts & spaces away.",image:"img/og/og-image-sql-style-guide.png",tags:["Marketing Cloud","SQL","Style Guide","Best Practice"]},sidebar:"docs",previous:{title:"Null Functions",permalink:"/docs/sql/sfmc-sql-null-functions"},next:{title:"\u203a SQL Snippets",permalink:"/docs/category/-sql-snippets"}},c={},d=[{value:"Letter Case",id:"letter-case",level:2},{value:"SQL Syntax Case",id:"sql-syntax-case",level:3},{value:"Column & Table Names Case",id:"column--table-names-case",level:3},{value:"Alignment and Indentation",id:"alignment-and-indentation",level:2},{value:"Single Information per Line",id:"single-information-per-line",level:3},{value:"Left Aligned Keywords",id:"left-aligned-keywords",level:3},{value:"Consistent Indentation",id:"consistent-indentation",level:3},{value:"Intentional Spacing",id:"intentional-spacing",level:3},{value:"Commas Placement",id:"commas-placement",level:3},{value:"Explicit vs Implicit",id:"explicit-vs-implicit",level:2},{value:"Date Parts",id:"date-parts",level:3},{value:"JOIN and ON",id:"join-and-on",level:3},{value:"Table Aliases",id:"table-aliases",level:3},{value:"Not Equal To Symbol",id:"not-equal-to-symbol",level:3},{value:"Meaningful Column Names",id:"meaningful-column-names",level:3},{value:"Sum Up",id:"sum-up",level:2}];function h(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",hr:"hr",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(l.U,{content:"Query with style. Readable, bug-free code is a few shifts & spaces away."}),"\n",(0,i.jsx)(n.p,{children:"First things first: this Salesforce Marketing Cloud SQL style guide is highly subjective. You may use it as it is, implement only some parts of it, or ignore it altogether. There are only two rules that I believe are a must-have:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Be consistent across your codebase."}),"\n",(0,i.jsx)(n.li,{children:"Strive for good readability."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Everything else is preference. And you are just about to learn about mine."}),"\n",(0,i.jsx)(n.h2,{id:"letter-case",children:"Letter Case"}),"\n",(0,i.jsx)(n.p,{children:"SQL gives you much freedom regarding the type of letter case you will be using for parts of your query. Let's use this freedom to create queries that are readable and aligned in convention to other Marketing Cloud programmatic languages operating on the same data."}),"\n",(0,i.jsx)(n.h3,{id:"sql-syntax-case",children:"SQL Syntax Case"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.code,{children:"UPPERCASE"})," for all elements of SQL syntax."]})}),"\n",(0,i.jsx)(n.p,{children:"This approach helps visually differentiate query language from Tables (data extensions, data views) and Columns (fields) to improve readability."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Upper Case for SQL Syntax */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n\n/* \u274c Pascal Case for SQL Syntax */\nSelect\n SubscriberKey\n , EmailAddress\nFrom Ent._Subscribers\nWhere DateJoined >= DateAdd(Month, -1, GetDate())\n\n/* \u274c Lower Case for SQL Syntax */\nselect\n SubscriberKey\n , EmailAddress\nfrom Ent._Subscribers\nwhere DateJoined >= dateadd(month, -1, getdate())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"column--table-names-case",children:"Column & Table Names Case"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.code,{children:"PascalCase"})," for all Table and Column names."]})}),"\n",(0,i.jsx)(n.p,{children:"Treat it as a soft recommendation, as it is highly connected to your organisation's conventions. If other connected systems are using a different style, it might be best to follow it in Marketing Cloud."}),"\n",(0,i.jsx)(n.p,{children:"It is especially true for Tables, as you might be using mixed convention leveraging lowercase, uppercase and underscores for Data Extension names. However, try not to use hyphens, as those will require you to use square brackets around the name and might interfere in query syntax highlighting, leading to worse readability."}),"\n",(0,i.jsxs)(n.p,{children:["The most popular SQL convention for Table and Column names is ",(0,i.jsx)(n.code,{children:"snake_case"}),". However, in Marketing Cloud, the Table and Column names will share the case between your queries and the User Interface. It is essential to make them as readable and human friendly as possible. Additionally, in many cases, you will also leverage those names in AMPScript and SSJS."]}),"\n",(0,i.jsxs)(n.p,{children:["Due to the above, I believe ",(0,i.jsx)(n.code,{children:"PascalCase"})," - especially for Column names - is the best choice for Marketing Cloud SQL."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Pascal Case for Table and Column names */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u2705 Pascal Case for Column names and custom consistent covention for Table names */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WEL_WelcomeCampaignSegment_20201011_OTH AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u274c Lower Case for Table and Column names */\nSELECT\n wel.subscriberkey\n , wel.emailaddress\n , o.eventdate AS opendate\nFROM welcomecampaignsegment AS wel\n INNER JOIN _open AS o\n ON o.subscriberkey = wel.subscriberkey\n\n/* \u274c Upper Case for Table and Column names */\nSELECT\n WEL.SUBSCRIBERKEY\n , WEL.EMAILADDRESS\n , O.EVENTDATE AS OPENDATE\nFROM WELCOMECAMPAIGNSEGMENT AS WEL\n INNER JOIN _OPEN AS O\n ON O.SUBSCRIBERKEY = WEL.SUBSCRIBERKEY\n"})}),"\n",(0,i.jsxs)(n.admonition,{title:"You Should Know",type:"note",children:[(0,i.jsx)(n.p,{children:"If you want to make your Style Guide even safer, you can decide on writing all Columns and Table names in square brackets. As Marketing Cloud is not checking whether you use SQL's reserved keywords, this approach will protect you from potential silent issue. The cost, however, is much more characters and less readable queries."}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:'title="You need to decide how hard you want to leverage the square brackets"',children:"SELECT\n [wel].[SubscriberKey]\n , [wel].[EmailAddress]\n , [o].[EventDate] AS [OpenDate]\nFROM [WelcomeCampaignSegment] AS [wel]\n INNER JOIN [_Open] AS [o]\n ON [o].[SubscriberKey] = [wel].[SubscriberKey]\n"})})]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h2,{id:"alignment-and-indentation",children:"Alignment and Indentation"}),"\n",(0,i.jsx)(n.p,{children:"SQL is very flexible when it comes to alignment and indentation of the query. Writing everything in one line creates a valid code that will run. But just because it is correct, it doesn't mean it is good. Generous use of new lines and indents has close to no impact on performance but a massive impact on readability. Enter and Space keys are your friends."}),"\n",(0,i.jsx)(n.p,{children:"There are many styles out there, and I decided to follow those that merge good writing speed with excellent readability."}),"\n",(0,i.jsx)(n.h3,{id:"single-information-per-line",children:"Single Information per Line"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Limit information per line to one."})}),"\n",(0,i.jsx)(n.p,{children:"I recommend keeping one information per line, as it allows for much easier scanning. The four most important examples of this approach are:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})})," Column in a separate line"]}),"\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where",children:(0,i.jsx)(n.code,{children:"WHERE"})})," condition in a separate line"]}),"\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})})," condition in a separate line"]}),"\n",(0,i.jsxs)(n.li,{children:["Each ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," and ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})})," relationship in a separate line"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Single information per line */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n ELSE 0\n END\n\n/* \u274c Multiple pieces of information per line */\nSELECT s.SubscriberKey AS SubscriberKey, j.EmailName AS EmailName, s.EventDate AS SentDate, j.DeliveredTime AS DeliveryDate, o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j ON j.JobID = s.JobID\n LEFT JOIN _Open AS o ON o.JobID = s.JobID AND o.ListID = s.ListID AND o.BatchID = s.BatchID AND o.SubscriberID = s.SubscriberID AND o.IsUnique = 1\nWHERE 1 = CASE WHEN j.EmailName LIKE 'UPS_%' THEN 1 WHEN j.EmailName LIKE 'CRS_%' THEN 1 ELSE 0 END\n"})}),"\n",(0,i.jsxs)(n.p,{children:["As you can see, the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})})," and ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where",children:(0,i.jsx)(n.code,{children:"WHERE"})})," keywords have their separate line to mark respective block starting. For readability reasons, I make an exception if there is only one Column or condition to be used:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Single Column in SELECT and single condition in WHERE lines */\nSELECT SubscriberKey\nFROM _Subscribers\nWHERE Domain = 'mateuszdabrowski.pl'\n\n/* \u274c Separate lines with single SELECT Column and WHERE condition */\nSELECT\n SubscriberKey\nFROM _Subscribers\nWHERE\n Domain = 'mateuszdabrowski.pl'\n"})}),"\n",(0,i.jsxs)(n.admonition,{title:"You Should Know",type:"note",children:[(0,i.jsxs)(n.p,{children:["If you are using ",(0,i.jsx)(n.code,{children:"DISTINCT"})," or ",(0,i.jsx)(n.code,{children:"TOP"}),", put it into the same line as ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})}),". In such a case, even if you work on a single Column, move it to a separate row for better readability."]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Single Column in SELECT and single condition in WHERE lines */\nSELECT DISTINCT TOP 10\n SubscriberKey\nFROM ContenstSubmissions\n\n/* \u274c Separate lines for single SELECT Column and WHERE condition */\nSELECT DISTINCT TOP 10 SubscriberKey\nFROM ContenstSubmissions\n"})})]}),"\n",(0,i.jsx)(n.h3,{id:"left-aligned-keywords",children:"Left Aligned Keywords"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Align main SQL keywords to the left."})}),"\n",(0,i.jsx)(n.p,{children:"This rule focuses on writing speed. While I prefer the Vertically Aligned Space approach's aesthetics, I don't see any significant readability gains. On the other hand, writing in this style in Marketing Cloud is a pain, as there is no autoformatter supporting it in the Query Studio or Query Activity. We would have to add all those additional spaces manually. It's just not worth it."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Left Aligned Keywords */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n\n/* \u274c Post Keyword Space Aligned Vertically */\nSELECT SubscriberKey,\n EmailAddress\n FROM Ent._Subscribers\n WHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"consistent-indentation",children:"Consistent Indentation"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use indentation to highlight SQL keyword relationships."})}),"\n",(0,i.jsx)(n.p,{children:"This rule focuses on readability. The logic, in short, is to indent whenever the line is dependent on the previous line (child line), for example:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Selected Column Names are children of ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select",children:(0,i.jsx)(n.code,{children:"SELECT"})})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," keywords are children of the initial Table referenced with ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-from",children:(0,i.jsx)(n.code,{children:"FROM"})})]}),"\n",(0,i.jsxs)(n.li,{children:["Joining relationships (",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})}),") are children of ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})]}),"\n",(0,i.jsxs)(n.li,{children:["Case conditions are children of the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})})]}),"\n",(0,i.jsxs)(n.li,{children:["Where conditions are children of the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where",children:(0,i.jsx)(n.code,{children:"WHERE"})})]}),"\n",(0,i.jsx)(n.li,{children:"Sub-queries follow the same rules in respective indentation level."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"For simplicity I use 4-spaces indent, as it is both standard and can be added in Marketing Cloud Query with a single click of the Tab key."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Dependency based indentation */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n ELSE 0\n END\n\n/* \u274c Lack of indentation */\nSELECT\ns.SubscriberKey AS SubscriberKey\n, j.EmailName AS EmailName\n, s.EventDate AS SentDate\n, j.DeliveredTime AS DeliveryDate\n, o.EventDate AS OpenDate\nFROM _Sent AS s\nLEFT JOIN _Job AS j ON j.JobID = s.JobID\nLEFT JOIN _Open AS o ON o.JobID = s.JobID\nAND o.ListID = s.ListID\nAND o.BatchID = s.BatchID\nAND o.SubscriberID = s.SubscriberID\nAND o.IsUnique = 1\nWHERE 1 = CASE\nWHEN j.EmailName LIKE 'UPS_%' THEN 1\nWHEN j.EmailName LIKE 'CRS_%' THEN 1\nELSE 0\nEND\n"})}),"\n",(0,i.jsx)(n.h3,{id:"intentional-spacing",children:"Intentional Spacing"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use spaces wherever it makes the query more readable."})}),"\n",(0,i.jsxs)(n.p,{children:["The must-have is spacing around any ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-where#basic-operators",children:"operators"})," (equality or comparison) and after commas."]}),"\n",(0,i.jsxs)(n.p,{children:["However, there is another place where spacing is beneficial for readability but might require an exception in some scenarios. Spacing for ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-select#aliasing-with-as",children:"aliases"})," and ",(0,i.jsx)(n.code,{children:"THEN"})," keywords of the ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})})," statement."]}),"\n",(0,i.jsxs)(n.p,{children:["I try to use it whenever possible, but when there is huge imbalance in length (for example one Column requires multi-function calculation or there is a single complex ",(0,i.jsx)(n.code,{children:"WHEN"})," in ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-case",children:(0,i.jsx)(n.code,{children:"CASE"})}),") equal spacing might make the query harder to read. Always decide which approach works best for your query from readability perspective."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 Spacing around operators plus equalizing aliases and THEN */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n WHEN j.EmailName = 'OTH_SeedList' THEN 1\n ELSE 0\n END\n\n/* \u2705 Spacing around operators plus equalizing aliases with exceptions */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\n , DATEDIFF(HOUR, s.EventDate, o.EventDate) AS TimeToOpen\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n AND o.ListID = s.ListID\n AND o.BatchID = s.BatchID\n AND o.SubscriberID = s.SubscriberID\n AND o.IsUnique = 1\nWHERE\n 1 = CASE\n WHEN j.EmailName LIKE 'UPS_%' OR j.EmailName LIKE 'CRS_%' THEN 1\n WHEN j.EmailName = 'OTH_SeedList' THEN 1\n ELSE 0\n END\n\n/* \u274c Lack of spacing */\nSELECT\n s.SubscriberKey AS SubscriberKey\n ,j.EmailName AS EmailName\n ,s.EventDate AS SentDate\n ,j.DeliveredTime AS DeliveryDate\n ,o.EventDate AS OpenDate\n ,DATEDIFF(HOUR,s.EventDate,o.EventDate) AS TimeToOpen\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID=s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID=s.JobID\n AND o.ListID=s.ListID\n AND o.BatchID=s.BatchID\n AND o.SubscriberID=s.SubscriberID\n AND o.IsUnique=1\nWHERE\n 1=CASE\n WHEN j.EmailName LIKE 'UPS_%' THEN 1\n WHEN j.EmailName LIKE 'CRS_%' THEN 1\n WHEN j.EmailName='OTH_SeedList' THEN 1\n ELSE 0\n END\n"})}),"\n",(0,i.jsx)(n.h3,{id:"commas-placement",children:"Commas Placement"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use commas at the beginning of the line."})}),"\n",(0,i.jsx)(n.p,{children:"There are few approaches related to comma placement. Initially, I favoured commas at the end of the line, as I found them more accessible to use due to their similarity to natural language. However, there are strong reasons to use the comma at the beginning of the line. Here is what convinced me to change my style:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Adding or deleting a Column requires a change in only one line. It's easier, faster and minimises the risk of a crash due to the trailing comma."}),"\n",(0,i.jsx)(n.li,{children:"Above is also very beneficial during difference checking and when leveraging git for query version control. With a comma at the beginning of the line, the Column addition or deletion is displayed correctly as a single line change."}),"\n",(0,i.jsxs)(n.li,{children:["Having a comma in the beginning makes it easier to assess where a new Column definition starts quickly. It is a vast readability improvement when you are using more complex structures, like ",(0,i.jsxs)(n.a,{href:"/docs/sql/sfmc-sql-case#conditional-values-with-case",children:[(0,i.jsx)(n.code,{children:"CASE"})," in ",(0,i.jsx)(n.code,{children:"SELECT"})]}),"."]}),"\n",(0,i.jsx)(n.li,{children:"It's also easier to quickly assess whether you have a comma for each Column. With lines of various length, it is much harder with the comma at the end."}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For the sake of readability, I indent the first Column by two spaces so that it is in line with the following ones. Similarly, I indent ",(0,i.jsx)(n.code,{children:"END"})," after ",(0,i.jsxs)(n.a,{href:"/docs/sql/sfmc-sql-case#conditional-values-with-case",children:[(0,i.jsx)(n.code,{children:"CASE"})," in ",(0,i.jsx)(n.code,{children:"SELECT"})]})," by two spaces for the same reason."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{3-5,10-12}",children:"/* \u2705 Commas at the beginning */\nSELECT\n SubscriberKey\n , EmailAddress\n , DateJoined\nFROM Ent._Subscribers\n\n/* \u274c Commas in the end */\nSELECT\n SubscriberKey,\n EmailAddress,\n DateJoined\nFROM Ent._Subscribers\n"})}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsx)(n.h2,{id:"explicit-vs-implicit",children:"Explicit vs Implicit"}),"\n",(0,i.jsx)(n.p,{children:"Many things in SQL can be done in multiple ways - using various functions, symbols or shortcuts. While all those options may work, not all are a good idea. Whenever you are choosing the approach, go for the explicit and straightforward. Even if it means writing a few characters more."}),"\n",(0,i.jsx)(n.h3,{id:"date-parts",children:"Date Parts"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use full ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-date-functions#date-parts",children:"Date Parts"})," names."]})}),"\n",(0,i.jsx)(n.p,{children:"Yes, abbreviations let you save few characters, but they kill the readability unless someone is fluent in those shortcuts. For Marketing Cloud purposes, the time saved during writing is not worth the time lost when reading. Go with the full version."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{6,13}",children:"/* \u2705 Full Date Part */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(MONTH, -1, GETDATE())\n\n/* \u274c Abbreviated Date Part */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\nWHERE DateJoined >= DATEADD(M, -1, GETDATE())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"join-and-on",children:"JOIN and ON"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"INNER JOIN"})})," name and reference Column from the new Table first after ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["Instead of just ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})}),", write ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#inner-join",children:(0,i.jsx)(n.code,{children:"INNER JOIN"})})," - it's longer but explicit and in line with the rest of ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," keywords. It makes it easier to scan queries with ",(0,i.jsxs)(n.a,{href:"/docs/sql/sfmc-sql-join#multiple-various-joins",children:["multiple various ",(0,i.jsx)(n.code,{children:"JOIN"})]})," statements."]}),"\n",(0,i.jsxs)(n.p,{children:["Additionally, when defining ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," relationships after ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#joining-on",children:(0,i.jsx)(n.code,{children:"ON"})}),", firstly reference the Column from the joined Table. The previous Table should be on the right side. It will improve consistency and reading speed."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{7-8,16-17}",children:"/* \u2705 Explicit Inner Join and Column from new Table on the left side of the ON condition */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u274c Implicit Inner Join and Column from new Table on the right side of the ON condition */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n JOIN _Open AS o\n ON wel.SubscriberKey = o.SubscriberKey\n"})}),"\n",(0,i.jsx)(n.h3,{id:"table-aliases",children:"Table Aliases"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["When using ",(0,i.jsx)(n.code,{children:"JOIN"}),", add meaningful aliases for Tables and prefix all Columns with them."]})}),"\n",(0,i.jsx)(n.p,{children:"There are a few points:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["If you are working on only one Table without ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," - don't use ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#table-name-prefix",children:"aliases"})," at all. They are not needed and would make the query less readable."]}),"\n",(0,i.jsxs)(n.li,{children:["If you have any ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join",children:(0,i.jsx)(n.code,{children:"JOIN"})})," - always use ",(0,i.jsx)(n.a,{href:"/docs/sql/sfmc-sql-join#table-name-prefix",children:"aliases and prefixes"}),". SQL doesn't always require it, but it is much easier to read the query when the Columns have an explicit Table mention in the prefix."]}),"\n",(0,i.jsx)(n.li,{children:"When you create an alias for a Table, make it meaningful. Using subsequent letters of the alphabet is not a good idea. Instead, use something that will remind the reader of the full name - for example, abbreviation using the first letter of each word in the Table. It will allow for much easier reading."}),"\n",(0,i.jsxs)(n.li,{children:["Always use ",(0,i.jsx)(n.code,{children:"AS"})," keyword between the Table name and the alias."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",children:"/* \u2705 No aliasing in single Table query */\nSELECT\n SubscriberKey\n , EmailAddress\nFROM Ent._Subscribers\n\n/* \u274c Aliasing in single Table query */\nSELECT\n s.SubscriberKey\n , s.EmailAddress\nFROM Ent._Subscribers AS s\n\n/* \u2705 Meaningful aliasing and prefixes in multi Table query */\nSELECT\n wel.SubscriberKey\n , wel.EmailAddress\n , o.EventDate AS OpenDate\nFROM WelcomeCampaignSegment AS wel\n INNER JOIN _Open AS o\n ON o.SubscriberKey = wel.SubscriberKey\n\n/* \u274c No aliasing and no prefix in multi Table query */\nSELECT\n SubscriberKey\n , EmailAddress\n , EventDate AS OpenDate\nFROM WelcomeCampaignSegment\n INNER JOIN _Open\n ON _Open.SubscriberKey = WelcomeCampaignSegment.SubscriberKey\n\n/* \u274c Not meaningful aliasing and no AS keyword in multi Table query */\nSELECT\n a.SubscriberKey\n , a.EmailAddress\n , b.EventDate AS OpenDate\nFROM WelcomeCampaignSegment a\n INNER JOIN _Open b\n ON a.SubscriberKey = b.SubscriberKey\n"})}),"\n",(0,i.jsx)(n.h3,{id:"not-equal-to-symbol",children:"Not Equal To Symbol"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Use ",(0,i.jsx)(n.code,{children:"!="})," instead of ",(0,i.jsx)(n.code,{children:"<>"}),"."]})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"!="})," symbol is much more popular and used in many languages. Using it makes the query more readable to people not experienced in SQL."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{4,9}",children:"/* \u2705 Use of != for negation */\nSELECT SubscriberKey\nFROM Ent._Subscribers\nWHERE CONVERT(DATE, DateJoined) != CONVERT(DATE, GETDATE())\n\n/* \u274c Use of <> for negation */\nSELECT SubscriberKey\nFROM Ent._Subscribers\nWHERE CONVERT(DATE, DateJoined) <> CONVERT(DATE, GETDATE())\n"})}),"\n",(0,i.jsx)(n.h3,{id:"meaningful-column-names",children:"Meaningful Column Names"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Use Column names that suggest the data type."})}),"\n",(0,i.jsx)(n.p,{children:"Just as with a letter case, you might have your hands tied by cross-system dependencies. But whenever possible, strive for meaningful names:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Use descriptive Column names. It is better to have a long explicit one (",(0,i.jsx)(n.code,{children:"IsTrackingSuppressed"}),") than a short mysterious abbreviation (",(0,i.jsx)(n.code,{children:"trk"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:["When the Column is a boolean, prefix it with ",(0,i.jsx)(n.code,{children:"Is"})," (or ",(0,i.jsx)(n.code,{children:"Has"}),"/",(0,i.jsx)(n.code,{children:"Does"})," depending on the underlying data)."]}),"\n",(0,i.jsxs)(n.li,{children:["When the Column is a date, suffix it with ",(0,i.jsx)(n.code,{children:"Date"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sql",metastring:"{3-8,17-22}",children:"/* \u2705 Meaningful and consistent Column Names */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryDate\n , o.EventDate AS OpenDate\n , j.SuppressTracking AS IsTrackingSuppressed\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n\n/* \u274c No consistency and type alignment in Column Names */\nSELECT\n s.SubscriberKey AS SubscriberKey\n , j.EmailName AS EmailName\n , s.EventDate AS SentDate\n , j.DeliveredTime AS DeliveryTime\n , o.EventDate AS OpenedAt\n , j.SuppressTracking AS SuppressTracking\nFROM _Sent AS s\n LEFT JOIN _Job AS j\n ON j.JobID = s.JobID\n LEFT JOIN _Open AS o\n ON o.JobID = s.JobID\n"})}),"\n",(0,i.jsx)(n.h2,{id:"sum-up",children:"Sum Up"}),"\n",(0,i.jsx)(n.p,{children:"It is a long article, so let's gather all the recommendations in one place:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Be consistent"}),"\n",(0,i.jsx)(n.li,{children:"Strive for readability"}),"\n",(0,i.jsx)(n.li,{children:"Use comments to provide required context to your query"}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"UPPERCASE"})," for SQL syntax ",(0,i.jsx)(n.a,{href:"#sql-syntax-case",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"PascalCase"})," for Table & Column names ",(0,i.jsx)(n.a,{href:"#column--table-names-case",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Limit information per line to one ",(0,i.jsx)(n.a,{href:"#single-information-per-line",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Align main SQL keywords to the left ",(0,i.jsx)(n.a,{href:"#left-aligned-keywords",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use indentation to highlight the relationship between SQL keywords ",(0,i.jsx)(n.a,{href:"#consistent-indentation",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use spaces wherever it makes the query more readable ",(0,i.jsx)(n.a,{href:"#intentional-spacing",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use commas at the beginning of the line ",(0,i.jsx)(n.a,{href:"#commas-placement",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use full Date Parts names ",(0,i.jsx)(n.a,{href:"#date-parts",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"INNER JOIN"})," name over ",(0,i.jsx)(n.code,{children:"JOIN"})," ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["In ",(0,i.jsx)(n.code,{children:"JOIN ON"})," reference Column from newly joined Table on the left ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["When using ",(0,i.jsx)(n.code,{children:"JOIN"}),", add meaningful aliases for Tables and prefix all Columns ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Always use ",(0,i.jsx)(n.code,{children:"AS"})," keyword between the Table name and the alias ",(0,i.jsx)(n.a,{href:"#join-and-on",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use ",(0,i.jsx)(n.code,{children:"!="})," instead of ",(0,i.jsx)(n.code,{children:"<>"})," ",(0,i.jsx)(n.a,{href:"#not-equal-to-symbol",children:"\ud83d\udd17"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use Column names that suggest the data type ",(0,i.jsx)(n.a,{href:"#meaningful-column-names",children:"\ud83d\udd17"})]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["If you want to share something I'm missing or have arguments for a different recommendation - ",(0,i.jsx)(n.a,{href:"https://www.linkedin.com/in/mateusz-dabrowski-pl/",children:"let me know"}),"."]}),"\n",(0,i.jsx)(n.p,{children:"Looking for more Marketing Cloud style? Check out my:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/ssjs/ssjs-style-guide",children:"SSJS Style Guide"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"/docs/ampscript/ampscript-style-guide",children:"AMPScript Style Guide"})}),"\n"]})]})}function m(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},6748:(e,n,s)=>{s.d(n,{U:()=>l});const i="leadText_qzwo";var a=s(4848);const l=e=>{let{content:n}=e;return(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("p",{id:i,children:n})})}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>t});var i=s(6540);const a={},l=i.createContext(a);function r(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function t(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:r(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/main.dfd8699e.js b/assets/js/main.c826b051.js similarity index 99% rename from assets/js/main.dfd8699e.js rename to assets/js/main.c826b051.js index 794b71e27..70cc7fe9e 100644 --- a/assets/js/main.dfd8699e.js +++ b/assets/js/main.c826b051.js @@ -1,2 +1,2 @@ -/*! For license information please see main.dfd8699e.js.LICENSE.txt */ -(self.webpackChunkmd=self.webpackChunkmd||[]).push([[8792],{5600:(e,t,n)=>{"use strict";n.d(t,{Bc:()=>h,E8:()=>$n,a1:()=>Un});var r=n(6540);n(961);function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function a(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function l(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a=[],s=!0,i=!1;try{for(n=n.call(e);!(s=(r=n.next()).done)&&(a.push(r.value),!t||a.length!==t);s=!0);}catch(e){i=!0,o=e}finally{try{s||null==n.return||n.return()}finally{if(i)throw o}}return a}}(e,t)||d(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function u(e){return function(e){if(Array.isArray(e))return f(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||d(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function d(e,t){if(e){if("string"==typeof e)return f(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?f(e,t):void 0}}function f(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function R(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function L(e){for(var t=1;t=3||2===n&&r>=4||1===n&&r>=10);function a(t,n,r){if(o&&void 0!==r){var a=r[0].__autocomplete_algoliaCredentials,s={"X-Algolia-Application-Id":a.appId,"X-Algolia-API-Key":a.apiKey};e.apply(void 0,[t].concat(P(n),[{headers:s}]))}else e.apply(void 0,[t].concat(P(n)))}return{init:function(t,n){e("init",{appId:t,apiKey:n})},setUserToken:function(t){e("setUserToken",t)},clickedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&a("clickedObjectIDsAfterSearch",M(t),t[0].items)},clickedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&a("clickedObjectIDs",M(t),t[0].items)},clickedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r0&&e.apply(void 0,["clickedFilters"].concat(n))},convertedObjectIDsAfterSearch:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&a("convertedObjectIDsAfterSearch",M(t),t[0].items)},convertedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&a("convertedObjectIDs",M(t),t[0].items)},convertedFilters:function(){for(var t=arguments.length,n=new Array(t),r=0;r0&&e.apply(void 0,["convertedFilters"].concat(n))},viewedObjectIDs:function(){for(var e=arguments.length,t=new Array(e),n=0;n0&&t.reduce((function(e,t){var n=t.items,r=N(t,T);return[].concat(P(e),P(function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:20,n=[],r=0;r0&&e.apply(void 0,["viewedFilters"].concat(n))}}}function B(e){var t=e.items.reduce((function(e,t){var n;return e[t.__autocomplete_indexName]=(null!==(n=e[t.__autocomplete_indexName])&&void 0!==n?n:[]).concat(t),e}),{});return Object.keys(t).map((function(e){return{index:e,items:t[e],algoliaSource:["autocomplete"]}}))}function z(e){return e.objectID&&e.__autocomplete_indexName&&e.__autocomplete_queryID}function q(e){return q="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},q(e)}function U(e){return function(e){if(Array.isArray(e))return $(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return $(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?$(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function $(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&K({onItemsChange:r,items:n,insights:i,state:t}))}}),0);return{name:"aa.algoliaInsightsPlugin",subscribe:function(e){var t=e.setContext,n=e.onSelect,r=e.onActive;s("addAlgoliaAgent","insights-plugin"),t({algoliaInsightsPlugin:{__algoliaSearchParameters:{clickAnalytics:!0},insights:i}}),n((function(e){var t=e.item,n=e.state,r=e.event;z(t)&&o({state:n,event:r,insights:i,item:t,insightsEvents:[V({eventName:"Item Selected"},j({item:t,items:c.current}))]})})),r((function(e){var t=e.item,n=e.state,r=e.event;z(t)&&a({state:n,event:r,insights:i,item:t,insightsEvents:[V({eventName:"Item Active"},j({item:t,items:c.current}))]})}))},onStateChange:function(e){var t=e.state;l({state:t})},__autocomplete_pluginOptions:e}}function Q(e,t){var n=t;return{then:function(t,r){return Q(e.then(X(t,n,e),X(r,n,e)),n)},catch:function(t){return Q(e.catch(X(t,n,e)),n)},finally:function(t){return t&&n.onCancelList.push(t),Q(e.finally(X(t&&function(){return n.onCancelList=[],t()},n,e)),n)},cancel:function(){n.isCanceled=!0;var e=n.onCancelList;n.onCancelList=[],e.forEach((function(e){e()}))},isCanceled:function(){return!0===n.isCanceled}}}function Z(e){return Q(e,{isCanceled:!1,onCancelList:[]})}function X(e,t,n){return e?function(n){return t.isCanceled?n:e(n)}:n}function J(e,t,n,r){if(!n)return null;if(e<0&&(null===t||null!==r&&0===t))return n+e;var o=(null===t?-1:t)+e;return o<=-1||o>=n?null===r?null:0:o}function ee(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function te(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n0},reshape:function(e){return e.sources}},e),{},{id:null!==(n=e.id)&&void 0!==n?n:"autocomplete-".concat(w++),plugins:o,initialState:he({activeItemId:null,query:"",completion:null,collections:[],isOpen:!1,status:"idle",context:{}},e.initialState),onStateChange:function(t){var n;null===(n=e.onStateChange)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onStateChange)||void 0===n?void 0:n.call(e,t)}))},onSubmit:function(t){var n;null===(n=e.onSubmit)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onSubmit)||void 0===n?void 0:n.call(e,t)}))},onReset:function(t){var n;null===(n=e.onReset)||void 0===n||n.call(e,t),o.forEach((function(e){var n;return null===(n=e.onReset)||void 0===n?void 0:n.call(e,t)}))},getSources:function(n){return Promise.all([].concat(function(e){return function(e){if(Array.isArray(e))return me(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return me(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?me(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(o.map((function(e){return e.getSources}))),[e.getSources]).filter(Boolean).map((function(e){return function(e,t){var n=[];return Promise.resolve(e(t)).then((function(e){return Promise.all(e.filter((function(e){return Boolean(e)})).map((function(e){if(e.sourceId,n.includes(e.sourceId))throw new Error("[Autocomplete] The `sourceId` ".concat(JSON.stringify(e.sourceId)," is not unique."));n.push(e.sourceId);var t={getItemInputValue:function(e){return e.state.query},getItemUrl:function(){},onSelect:function(e){(0,e.setIsOpen)(!1)},onActive:E,onResolve:E};Object.keys(t).forEach((function(e){t[e].__default=!0}));var r=te(te({},t),e);return Promise.resolve(r)})))}))}(e,n)}))).then((function(e){return v(e)})).then((function(e){return e.map((function(e){return he(he({},e),{},{onSelect:function(n){e.onSelect(n),t.forEach((function(e){var t;return null===(t=e.onSelect)||void 0===t?void 0:t.call(e,n)}))},onActive:function(n){e.onActive(n),t.forEach((function(e){var t;return null===(t=e.onActive)||void 0===t?void 0:t.call(e,n)}))},onResolve:function(n){e.onResolve(n),t.forEach((function(e){var t;return null===(t=e.onResolve)||void 0===t?void 0:t.call(e,n)}))}})}))}))},navigator:he({navigate:function(e){var t=e.itemUrl;r.location.assign(t)},navigateNewTab:function(e){var t=e.itemUrl,n=r.open(t,"_blank","noopener");null==n||n.focus()},navigateNewWindow:function(e){var t=e.itemUrl;r.open(t,"_blank","noopener")}},e.navigator)})}function ve(e){return ve="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ve(e)}function we(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Se(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,Ie);Be&&o.environment.clearTimeout(Be);var l=c.setCollections,u=c.setIsOpen,d=c.setQuery,f=c.setActiveItemId,p=c.setStatus;if(d(a),f(o.defaultActiveItemId),!a&&!1===o.openOnFocus){var m,g=i.getState().collections.map((function(e){return Re(Re({},e),{},{items:[]})}));p("idle"),l(g),u(null!==(m=r.isOpen)&&void 0!==m?m:o.shouldPanelOpen({state:i.getState()}));var h=Z(ze(g).then((function(){return Promise.resolve()})));return i.pendingRequests.add(h)}p("loading"),Be=o.environment.setTimeout((function(){p("stalled")}),o.stallThreshold);var b=Z(ze(o.getSources(Re({query:a,refresh:s,state:i.getState()},c)).then((function(e){return Promise.all(e.map((function(e){return Promise.resolve(e.getItems(Re({query:a,refresh:s,state:i.getState()},c))).then((function(t){return function(e,t,n){if(o=e,Boolean(null==o?void 0:o.execute)){var r="algolia"===e.requesterId?Object.assign.apply(Object,[{}].concat(Oe(Object.keys(n.context).map((function(e){var t;return null===(t=n.context[e])||void 0===t?void 0:t.__algoliaSearchParameters}))))):{};return _e(_e({},e),{},{requests:e.queries.map((function(n){return{query:"algolia"===e.requesterId?_e(_e({},n),{},{params:_e(_e({},r),n.params)}):n,sourceId:t,transformResponse:e.transformResponse}}))})}var o;return{items:e,sourceId:t}}(t,e.sourceId,i.getState())}))}))).then(Ae).then((function(t){return function(e,t,n){return t.map((function(t){var r,o=e.filter((function(e){return e.sourceId===t.sourceId})),a=o.map((function(e){return e.items})),s=o[0].transformResponse,i=s?s({results:r=a,hits:r.map((function(e){return e.hits})).filter(Boolean),facetHits:r.map((function(e){var t;return null===(t=e.facetHits)||void 0===t?void 0:t.map((function(e){return{label:e.value,count:e.count,_highlightResult:{label:{value:e.highlighted}}}}))})).filter(Boolean)}):a;return t.onResolve({source:t,results:a,items:i,state:n.getState()}),i.every(Boolean),'The `getItems` function from source "'.concat(t.sourceId,'" must return an array of items but returned ').concat(JSON.stringify(void 0),".\n\nDid you forget to return items?\n\nSee: https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/sources/#param-getitems"),{source:t,items:i}}))}(t,e,i)})).then((function(e){return function(e){var t=e.props,n=e.state,r=e.collections.reduce((function(e,t){return Se(Se({},e),{},xe({},t.source.sourceId,Se(Se({},t.source),{},{getItems:function(){return v(t.items)}})))}),{}),o=t.plugins.reduce((function(e,t){return t.reshape?t.reshape(e):e}),{sourcesBySourceId:r,state:n}).sourcesBySourceId;return v(t.reshape({sourcesBySourceId:o,sources:Object.values(o),state:n})).filter(Boolean).map((function(e){return{source:e,items:e.getItems()}}))}({collections:e,props:o,state:i.getState()})}))})))).then((function(e){var n;p("idle"),l(e);var d=o.shouldPanelOpen({state:i.getState()});u(null!==(n=r.isOpen)&&void 0!==n?n:o.openOnFocus&&!a&&d||d);var f=oe(i.getState());if(null!==i.getState().activeItemId&&f){var m=f.item,g=f.itemInputValue,h=f.itemUrl,b=f.source;b.onActive(Re({event:t,item:m,itemInputValue:g,itemUrl:h,refresh:s,source:b,state:i.getState()},c))}})).finally((function(){p("idle"),Be&&o.environment.clearTimeout(Be)}));return i.pendingRequests.add(b)}function Ue(e){return Ue="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ue(e)}var $e=["event","props","refresh","store"];function He(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Ve(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function at(e){var t=e.props,n=e.refresh,r=e.store,o=ot(e,Ke),a=function(e,t){return void 0!==t?"".concat(e,"-").concat(t):e};return{getEnvironmentProps:function(e){var n=e.inputElement,o=e.formElement,a=e.panelElement;function s(e){!r.getState().isOpen&&r.pendingRequests.isEmpty()||e.target===n||!1===[o,a].some((function(t){return(n=t)===(r=e.target)||n.contains(r);var n,r}))&&(r.dispatch("blur",null),t.debug||r.pendingRequests.cancelAll())}return nt({onTouchStart:s,onMouseDown:s,onTouchMove:function(e){!1!==r.getState().isOpen&&n===t.environment.document.activeElement&&e.target!==n&&n.blur()}},ot(e,Ye))},getRootProps:function(e){return nt({role:"combobox","aria-expanded":r.getState().isOpen,"aria-haspopup":"listbox","aria-owns":r.getState().isOpen?"".concat(t.id,"-list"):void 0,"aria-labelledby":"".concat(t.id,"-label")},e)},getFormProps:function(e){return e.inputElement,nt({action:"",noValidate:!0,role:"search",onSubmit:function(a){var s;a.preventDefault(),t.onSubmit(nt({event:a,refresh:n,state:r.getState()},o)),r.dispatch("submit",null),null===(s=e.inputElement)||void 0===s||s.blur()},onReset:function(a){var s;a.preventDefault(),t.onReset(nt({event:a,refresh:n,state:r.getState()},o)),r.dispatch("reset",null),null===(s=e.inputElement)||void 0===s||s.focus()}},ot(e,Qe))},getLabelProps:function(e){var n=e||{},r=n.sourceIndex,o=ot(n,Xe);return nt({htmlFor:"".concat(a(t.id,r),"-input"),id:"".concat(a(t.id,r),"-label")},o)},getInputProps:function(e){var a;function s(e){(t.openOnFocus||Boolean(r.getState().query))&&qe(nt({event:e,props:t,query:r.getState().completion||r.getState().query,refresh:n,store:r},o)),r.dispatch("focus",null)}var i=e||{},c=(i.inputElement,i.maxLength),l=void 0===c?512:c,u=ot(i,Ze),d=oe(r.getState()),f=function(e){return Boolean(e&&e.match(ae))}((null===(a=t.environment.navigator)||void 0===a?void 0:a.userAgent)||""),p=null!=d&&d.itemUrl&&!f?"go":"search";return nt({"aria-autocomplete":"both","aria-activedescendant":r.getState().isOpen&&null!==r.getState().activeItemId?"".concat(t.id,"-item-").concat(r.getState().activeItemId):void 0,"aria-controls":r.getState().isOpen?"".concat(t.id,"-list"):void 0,"aria-labelledby":"".concat(t.id,"-label"),value:r.getState().completion||r.getState().query,id:"".concat(t.id,"-input"),autoComplete:"off",autoCorrect:"off",autoCapitalize:"off",enterKeyHint:p,spellCheck:"false",autoFocus:t.autoFocus,placeholder:t.placeholder,maxLength:l,type:"search",onChange:function(e){qe(nt({event:e,props:t,query:e.currentTarget.value.slice(0,l),refresh:n,store:r},o))},onKeyDown:function(e){!function(e){var t=e.event,n=e.props,r=e.refresh,o=e.store,a=function(e,t){if(null==e)return{};var n,r,o=function(e,t){if(null==e)return{};var n,r,o={},a=Object.keys(e);for(r=0;r=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}(e,$e);if("ArrowUp"===t.key||"ArrowDown"===t.key){var s=function(){var e=n.environment.document.getElementById("".concat(n.id,"-item-").concat(o.getState().activeItemId));e&&(e.scrollIntoViewIfNeeded?e.scrollIntoViewIfNeeded(!1):e.scrollIntoView(!1))},i=function(){var e=oe(o.getState());if(null!==o.getState().activeItemId&&e){var n=e.item,s=e.itemInputValue,i=e.itemUrl,c=e.source;c.onActive(Ve({event:t,item:n,itemInputValue:s,itemUrl:i,refresh:r,source:c,state:o.getState()},a))}};t.preventDefault(),!1===o.getState().isOpen&&(n.openOnFocus||Boolean(o.getState().query))?qe(Ve({event:t,props:n,query:o.getState().query,refresh:r,store:o},a)).then((function(){o.dispatch(t.key,{nextActiveItemId:n.defaultActiveItemId}),i(),setTimeout(s,0)})):(o.dispatch(t.key,{}),i(),s())}else if("Escape"===t.key)t.preventDefault(),o.dispatch(t.key,null),o.pendingRequests.cancelAll();else if("Tab"===t.key)o.dispatch("blur",null),o.pendingRequests.cancelAll();else if("Enter"===t.key){if(null===o.getState().activeItemId||o.getState().collections.every((function(e){return 0===e.items.length})))return void(n.debug||o.pendingRequests.cancelAll());t.preventDefault();var c=oe(o.getState()),l=c.item,u=c.itemInputValue,d=c.itemUrl,f=c.source;if(t.metaKey||t.ctrlKey)void 0!==d&&(f.onSelect(Ve({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:f,state:o.getState()},a)),n.navigator.navigateNewTab({itemUrl:d,item:l,state:o.getState()}));else if(t.shiftKey)void 0!==d&&(f.onSelect(Ve({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:f,state:o.getState()},a)),n.navigator.navigateNewWindow({itemUrl:d,item:l,state:o.getState()}));else if(t.altKey);else{if(void 0!==d)return f.onSelect(Ve({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:f,state:o.getState()},a)),void n.navigator.navigate({itemUrl:d,item:l,state:o.getState()});qe(Ve({event:t,nextState:{isOpen:!1},props:n,query:u,refresh:r,store:o},a)).then((function(){f.onSelect(Ve({event:t,item:l,itemInputValue:u,itemUrl:d,refresh:r,source:f,state:o.getState()},a))}))}}}(nt({event:e,props:t,refresh:n,store:r},o))},onFocus:s,onBlur:E,onClick:function(n){e.inputElement!==t.environment.document.activeElement||r.getState().isOpen||s(n)}},u)},getPanelProps:function(e){return nt({onMouseDown:function(e){e.preventDefault()},onMouseLeave:function(){r.dispatch("mouseleave",null)}},e)},getListProps:function(e){var n=e||{},r=n.sourceIndex,o=ot(n,Je);return nt({role:"listbox","aria-labelledby":"".concat(a(t.id,r),"-label"),id:"".concat(a(t.id,r),"-list")},o)},getItemProps:function(e){var s=e.item,i=e.source,c=e.sourceIndex,l=ot(e,et);return nt({id:"".concat(a(t.id,c),"-item-").concat(s.__autocomplete_id),role:"option","aria-selected":r.getState().activeItemId===s.__autocomplete_id,onMouseMove:function(e){if(s.__autocomplete_id!==r.getState().activeItemId){r.dispatch("mousemove",s.__autocomplete_id);var t=oe(r.getState());if(null!==r.getState().activeItemId&&t){var a=t.item,i=t.itemInputValue,c=t.itemUrl,l=t.source;l.onActive(nt({event:e,item:a,itemInputValue:i,itemUrl:c,refresh:n,source:l,state:r.getState()},o))}}},onMouseDown:function(e){e.preventDefault()},onClick:function(e){var a=i.getItemInputValue({item:s,state:r.getState()}),c=i.getItemUrl({item:s,state:r.getState()});(c?Promise.resolve():qe(nt({event:e,nextState:{isOpen:!1},props:t,query:a,refresh:n,store:r},o))).then((function(){i.onSelect(nt({event:e,item:s,itemInputValue:a,itemUrl:c,refresh:n,source:i,state:r.getState()},o))}))}},l)}}}function st(e){return st="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},st(e)}function it(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function ct(e){for(var t=1;t0&&r.createElement("div",{className:"DocSearch-NoResults-Prefill-List"},r.createElement("p",{className:"DocSearch-Help"},l,":"),r.createElement("ul",null,g.slice(0,3).reduce((function(e,t){return[].concat(u(e),[r.createElement("li",{key:t},r.createElement("button",{className:"DocSearch-Prefill",key:t,type:"button",onClick:function(){o.setQuery(t.toLowerCase()+" "),o.refresh(),o.inputRef.current.focus()}},t))])}),[]))),o.getMissingResultsUrl&&r.createElement("p",{className:"DocSearch-Help"},"".concat(f," "),r.createElement("a",{href:o.getMissingResultsUrl({query:o.state.query}),target:"_blank",rel:"noopener noreferrer"},m)))}var zt=["hit","attribute","tagName"];function qt(e,t){return t.split(".").reduce((function(e,t){return null!=e&&e[t]?e[t]:null}),e)}function Ut(e){var t=e.hit,n=e.attribute,o=e.tagName,s=void 0===o?"span":o,i=c(e,zt);return(0,r.createElement)(s,a(a({},i),{},{dangerouslySetInnerHTML:{__html:qt(t,"_snippetResult.".concat(n,".value"))||qt(t,n)}}))}function $t(e){return e.collection&&0!==e.collection.items.length?r.createElement("section",{className:"DocSearch-Hits"},r.createElement("div",{className:"DocSearch-Hit-source"},e.title),r.createElement("ul",e.getListProps(),e.collection.items.map((function(t,n){return r.createElement(Ht,i({key:[e.title,t.objectID].join(":"),item:t,index:n},e))})))):null}function Ht(e){var t=e.item,n=e.index,o=e.renderIcon,a=e.renderAction,s=e.getItemProps,c=e.onItemClick,u=e.collection,d=e.hitComponent,f=l(r.useState(!1),2),p=f[0],m=f[1],g=l(r.useState(!1),2),h=g[0],b=g[1],y=r.useRef(null),v=d;return r.createElement("li",i({className:["DocSearch-Hit",t.__docsearch_parent&&"DocSearch-Hit--Child",p&&"DocSearch-Hit--deleting",h&&"DocSearch-Hit--favoriting"].filter(Boolean).join(" "),onTransitionEnd:function(){y.current&&y.current()}},s({item:t,source:u.source,onClick:function(e){c(t,e)}})),r.createElement(v,{hit:t},r.createElement("div",{className:"DocSearch-Hit-Container"},o({item:t,index:n}),t.hierarchy[t.type]&&"lvl1"===t.type&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(Ut,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.lvl1"}),t.content&&r.createElement(Ut,{className:"DocSearch-Hit-path",hit:t,attribute:"content"})),t.hierarchy[t.type]&&("lvl2"===t.type||"lvl3"===t.type||"lvl4"===t.type||"lvl5"===t.type||"lvl6"===t.type)&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(Ut,{className:"DocSearch-Hit-title",hit:t,attribute:"hierarchy.".concat(t.type)}),r.createElement(Ut,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),"content"===t.type&&r.createElement("div",{className:"DocSearch-Hit-content-wrapper"},r.createElement(Ut,{className:"DocSearch-Hit-title",hit:t,attribute:"content"}),r.createElement(Ut,{className:"DocSearch-Hit-path",hit:t,attribute:"hierarchy.lvl1"})),a({item:t,runDeleteTransition:function(e){m(!0),y.current=e},runFavoriteTransition:function(e){b(!0),y.current=e}}))))}function Vt(e,t,n){return e.reduce((function(e,r){var o=t(r);return e.hasOwnProperty(o)||(e[o]=[]),e[o].length<(n||5)&&e[o].push(r),e}),{})}function Wt(e){return e}function Gt(e){return 1===e.button||e.altKey||e.ctrlKey||e.metaKey||e.shiftKey}function Kt(){}var Yt=/(|<\/mark>)/g,Qt=RegExp(Yt.source);function Zt(e){var t,n,r=e;if(!r.__docsearch_parent&&!e._highlightResult)return e.hierarchy.lvl0;var o=((r.__docsearch_parent?null===(t=r.__docsearch_parent)||void 0===t||null===(t=t._highlightResult)||void 0===t||null===(t=t.hierarchy)||void 0===t?void 0:t.lvl0:null===(n=e._highlightResult)||void 0===n||null===(n=n.hierarchy)||void 0===n?void 0:n.lvl0)||{}).value;return o&&Qt.test(o)?o.replace(Yt,""):o}function Xt(e){return r.createElement("div",{className:"DocSearch-Dropdown-Container"},e.state.collections.map((function(t){if(0===t.items.length)return null;var n=Zt(t.items[0]);return r.createElement($t,i({},e,{key:t.source.sourceId,title:n,collection:t,renderIcon:function(e){var n,o=e.item,a=e.index;return r.createElement(r.Fragment,null,o.__docsearch_parent&&r.createElement("svg",{className:"DocSearch-Hit-Tree",viewBox:"0 0 24 54"},r.createElement("g",{stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"},o.__docsearch_parent!==(null===(n=t.items[a+1])||void 0===n?void 0:n.__docsearch_parent)?r.createElement("path",{d:"M8 6v21M20 27H8.3"}):r.createElement("path",{d:"M8 6v42M20 27H8.3"}))),r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Pt,{type:o.type})))},renderAction:function(){return r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement(Tt,null))}}))})),e.resultsFooterComponent&&r.createElement("section",{className:"DocSearch-HitsFooter"},r.createElement(e.resultsFooterComponent,{state:e.state})))}var Jt=["translations"];function en(e){var t=e.translations,n=void 0===t?{}:t,o=c(e,Jt),a=n.recentSearchesTitle,s=void 0===a?"Recent":a,l=n.noRecentSearchesText,u=void 0===l?"No recent searches":l,d=n.saveRecentSearchButtonTitle,f=void 0===d?"Save this search":d,p=n.removeRecentSearchButtonTitle,m=void 0===p?"Remove this search from history":p,g=n.favoriteSearchesTitle,h=void 0===g?"Favorite":g,b=n.removeFavoriteSearchButtonTitle,y=void 0===b?"Remove this search from favorites":b;return"idle"===o.state.status&&!1===o.hasCollections?o.disableUserPersonalization?null:r.createElement("div",{className:"DocSearch-StartScreen"},r.createElement("p",{className:"DocSearch-Help"},u)):!1===o.hasCollections?null:r.createElement("div",{className:"DocSearch-Dropdown-Container"},r.createElement($t,i({},o,{title:s,collection:o.state.collections[0],renderIcon:function(){return r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Ot,null))},renderAction:function(e){var t=e.item,n=e.runFavoriteTransition,a=e.runDeleteTransition;return r.createElement(r.Fragment,null,r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:f,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),n((function(){o.favoriteSearches.add(t),o.recentSearches.remove(t),o.refresh()}))}},r.createElement(Rt,null))),r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:m,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),a((function(){o.recentSearches.remove(t),o.refresh()}))}},r.createElement(Ct,null))))}})),r.createElement($t,i({},o,{title:h,collection:o.state.collections[1],renderIcon:function(){return r.createElement("div",{className:"DocSearch-Hit-icon"},r.createElement(Rt,null))},renderAction:function(e){var t=e.item,n=e.runDeleteTransition;return r.createElement("div",{className:"DocSearch-Hit-action"},r.createElement("button",{className:"DocSearch-Hit-action-button",title:y,type:"submit",onClick:function(e){e.preventDefault(),e.stopPropagation(),n((function(){o.favoriteSearches.remove(t),o.refresh()}))}},r.createElement(Ct,null)))}})))}var tn=["translations"],nn=r.memo((function(e){var t=e.translations,n=void 0===t?{}:t,o=c(e,tn);if("error"===o.state.status)return r.createElement(Mt,{translations:null==n?void 0:n.errorScreen});var a=o.state.collections.some((function(e){return e.items.length>0}));return o.state.query?!1===a?r.createElement(Bt,i({},o,{translations:null==n?void 0:n.noResultsScreen})):r.createElement(Xt,o):r.createElement(en,i({},o,{hasCollections:a,translations:null==n?void 0:n.startScreen}))}),(function(e,t){return"loading"===t.state.status||"stalled"===t.state.status})),rn=["translations"];function on(e){var t=e.translations,n=void 0===t?{}:t,o=c(e,rn),a=n.resetButtonTitle,s=void 0===a?"Clear the query":a,l=n.resetButtonAriaLabel,u=void 0===l?"Clear the query":l,d=n.cancelButtonText,f=void 0===d?"Cancel":d,p=n.cancelButtonAriaLabel,g=void 0===p?"Cancel":p,h=n.searchInputLabel,b=void 0===h?"Search":h,y=o.getFormProps({inputElement:o.inputRef.current}).onReset;return r.useEffect((function(){o.autoFocus&&o.inputRef.current&&o.inputRef.current.focus()}),[o.autoFocus,o.inputRef]),r.useEffect((function(){o.isFromSelection&&o.inputRef.current&&o.inputRef.current.select()}),[o.isFromSelection,o.inputRef]),r.createElement(r.Fragment,null,r.createElement("form",{className:"DocSearch-Form",onSubmit:function(e){e.preventDefault()},onReset:y},r.createElement("label",i({className:"DocSearch-MagnifierLabel"},o.getLabelProps()),r.createElement(m,null),r.createElement("span",{className:"DocSearch-VisuallyHiddenForAccessibility"},b)),r.createElement("div",{className:"DocSearch-LoadingIndicator"},r.createElement(jt,null)),r.createElement("input",i({className:"DocSearch-Input",ref:o.inputRef},o.getInputProps({inputElement:o.inputRef.current,autoFocus:o.autoFocus,maxLength:64}))),r.createElement("button",{type:"reset",title:s,className:"DocSearch-Reset","aria-label":u,hidden:!o.state.query},r.createElement(Ct,null))),r.createElement("button",{className:"DocSearch-Cancel",type:"reset","aria-label":g,onClick:o.onClose},f))}var an=["_highlightResult","_snippetResult"];function sn(e){var t=e.key,n=e.limit,r=void 0===n?5:n,o=function(e){return!1===function(){var e="__TEST_KEY__";try{return localStorage.setItem(e,""),localStorage.removeItem(e),!0}catch(e){return!1}}()?{setItem:function(){},getItem:function(){return[]}}:{setItem:function(t){return window.localStorage.setItem(e,JSON.stringify(t))},getItem:function(){var t=window.localStorage.getItem(e);return t?JSON.parse(t):[]}}}(t),a=o.getItem().slice(0,r);return{add:function(e){var t=e,n=(t._highlightResult,t._snippetResult,c(t,an)),s=a.findIndex((function(e){return e.objectID===n.objectID}));s>-1&&a.splice(s,1),a.unshift(n),a=a.slice(0,r),o.setItem(a)},remove:function(e){a=a.filter((function(t){return t.objectID!==e.objectID})),o.setItem(a)},getAll:function(){return a}}}function cn(e){const t=`algoliasearch-client-js-${e.key}`;let n;const r=()=>(void 0===n&&(n=e.localStorage||window.localStorage),n),o=()=>JSON.parse(r().getItem(t)||"{}"),a=e=>{r().setItem(t,JSON.stringify(e))};return{get:(t,n,r={miss:()=>Promise.resolve()})=>Promise.resolve().then((()=>{(()=>{const t=e.timeToLive?1e3*e.timeToLive:null,n=o(),r=Object.fromEntries(Object.entries(n).filter((([,e])=>void 0!==e.timestamp)));if(a(r),!t)return;const s=Object.fromEntries(Object.entries(r).filter((([,e])=>{const n=(new Date).getTime();return!(e.timestamp+tPromise.all([e?e.value:n(),void 0!==e]))).then((([e,t])=>Promise.all([e,t||r.miss(e)]))).then((([e])=>e)),set:(e,n)=>Promise.resolve().then((()=>{const a=o();return a[JSON.stringify(e)]={timestamp:(new Date).getTime(),value:n},r().setItem(t,JSON.stringify(a)),n})),delete:e=>Promise.resolve().then((()=>{const n=o();delete n[JSON.stringify(e)],r().setItem(t,JSON.stringify(n))})),clear:()=>Promise.resolve().then((()=>{r().removeItem(t)}))}}function ln(e){const t=[...e.caches],n=t.shift();return void 0===n?{get:(e,t,n={miss:()=>Promise.resolve()})=>t().then((e=>Promise.all([e,n.miss(e)]))).then((([e])=>e)),set:(e,t)=>Promise.resolve(t),delete:e=>Promise.resolve(),clear:()=>Promise.resolve()}:{get:(e,r,o={miss:()=>Promise.resolve()})=>n.get(e,r,o).catch((()=>ln({caches:t}).get(e,r,o))),set:(e,r)=>n.set(e,r).catch((()=>ln({caches:t}).set(e,r))),delete:e=>n.delete(e).catch((()=>ln({caches:t}).delete(e))),clear:()=>n.clear().catch((()=>ln({caches:t}).clear()))}}function un(e={serializable:!0}){let t={};return{get(n,r,o={miss:()=>Promise.resolve()}){const a=JSON.stringify(n);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);const s=r(),i=o&&o.miss||(()=>Promise.resolve());return s.then((e=>i(e))).then((()=>s))},set:(n,r)=>(t[JSON.stringify(n)]=e.serializable?JSON.stringify(r):r,Promise.resolve(r)),delete:e=>(delete t[JSON.stringify(e)],Promise.resolve()),clear:()=>(t={},Promise.resolve())}}function dn(e){let t=e.length-1;for(;t>0;t--){const n=Math.floor(Math.random()*(t+1)),r=e[t];e[t]=e[n],e[n]=r}return e}function fn(e,t){return t?(Object.keys(t).forEach((n=>{e[n]=t[n](e)})),e):e}function pn(e,...t){let n=0;return e.replace(/%s/g,(()=>encodeURIComponent(t[n++])))}const mn={WithinQueryParameters:0,WithinHeaders:1};function gn(e,t){const n=e||{},r=n.data||{};return Object.keys(n).forEach((e=>{-1===["timeout","headers","queryParameters","data","cacheable"].indexOf(e)&&(r[e]=n[e])})),{data:Object.entries(r).length>0?r:void 0,timeout:n.timeout||t,headers:n.headers||{},queryParameters:n.queryParameters||{},cacheable:n.cacheable}}const hn={Read:1,Write:2,Any:3},bn=1,yn=3;function vn(e,t=bn){return{...e,status:t,lastUpdate:Date.now()}}function wn(e){return"string"==typeof e?{protocol:"https",url:e,accept:hn.Any}:{protocol:e.protocol||"https",url:e.url,accept:e.accept||hn.Any}}const Sn="GET",xn="POST";function kn(e,t,n,r){const o=[],a=function(e,t){if(e.method===Sn||void 0===e.data&&void 0===t.data)return;const n=Array.isArray(e.data)?e.data:{...e.data,...t.data};return JSON.stringify(n)}(n,r),s=function(e,t){const n={...e.headers,...t.headers},r={};return Object.keys(n).forEach((e=>{const t=n[e];r[e.toLowerCase()]=t})),r}(e,r),i=n.method,c=n.method!==Sn?{}:{...n.data,...r.data},l={"x-algolia-agent":e.userAgent.value,...e.queryParameters,...c,...r.queryParameters};let u=0;const d=(t,c)=>{const f=t.pop();if(void 0===f)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:On(o)};const p={data:a,headers:s,method:i,url:_n(f,n.path,l),connectTimeout:c(u,e.timeouts.connect),responseTimeout:c(u,r.timeout)},m=e=>{const n={request:p,response:e,host:f,triesLeft:t.length};return o.push(n),n},g={onSuccess:e=>function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e),onRetry(n){const r=m(n);return n.isTimedOut&&u++,Promise.all([e.logger.info("Retryable failure",Cn(r)),e.hostsCache.set(f,vn(f,n.isTimedOut?yn:2))]).then((()=>d(t,c)))},onFail(e){throw m(e),function({content:e,status:t},n){let r=e;try{r=JSON.parse(e).message}catch(e){}return function(e,t,n){return{name:"ApiError",message:e,status:t,transporterStackTrace:n}}(r,t,n)}(e,On(o))}};return e.requester.send(p).then((e=>((e,t)=>(e=>{const t=e.status;return e.isTimedOut||(({isTimedOut:e,status:t})=>!e&&!~~t)(e)||2!=~~(t/100)&&4!=~~(t/100)})(e)?t.onRetry(e):(({status:e})=>2==~~(e/100))(e)?t.onSuccess(e):t.onFail(e))(e,g)))};return function(e,t){return Promise.all(t.map((t=>e.get(t,(()=>Promise.resolve(vn(t))))))).then((e=>{const n=e.filter((e=>function(e){return e.status===bn||Date.now()-e.lastUpdate>12e4}(e))),r=e.filter((e=>function(e){return e.status===yn&&Date.now()-e.lastUpdate<=12e4}(e))),o=[...n,...r];return{getTimeout:(e,t)=>(0===r.length&&0===e?1:r.length+3+e)*t,statelessHosts:o.length>0?o.map((e=>wn(e))):t}}))}(e.hostsCache,t).then((e=>d([...e.statelessHosts].reverse(),e.getTimeout)))}function En(e){const t={value:`Algolia for JavaScript (${e})`,add(e){const n=`; ${e.segment}${void 0!==e.version?` (${e.version})`:""}`;return-1===t.value.indexOf(n)&&(t.value=`${t.value}${n}`),t}};return t}function _n(e,t,n){const r=jn(n);let o=`${e.protocol}://${e.url}/${"/"===t.charAt(0)?t.substr(1):t}`;return r.length&&(o+=`?${r}`),o}function jn(e){return Object.keys(e).map((t=>{return pn("%s=%s",t,(n=e[t],"[object Object]"===Object.prototype.toString.call(n)||"[object Array]"===Object.prototype.toString.call(n)?JSON.stringify(e[t]):e[t]));var n})).join("&")}function On(e){return e.map((e=>Cn(e)))}function Cn(e){const t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return{...e,request:{...e.request,headers:{...e.request.headers,...t}}}}const Tn=e=>{const t=e.appId,n=function(e,t,n){const r={"x-algolia-api-key":n,"x-algolia-application-id":t};return{headers:()=>e===mn.WithinHeaders?r:{},queryParameters:()=>e===mn.WithinQueryParameters?r:{}}}(void 0!==e.authMode?e.authMode:mn.WithinHeaders,t,e.apiKey),r=function(e){const{hostsCache:t,logger:n,requester:r,requestsCache:o,responsesCache:a,timeouts:s,userAgent:i,hosts:c,queryParameters:l,headers:u}=e,d={hostsCache:t,logger:n,requester:r,requestsCache:o,responsesCache:a,timeouts:s,userAgent:i,headers:u,queryParameters:l,hosts:c.map((e=>wn(e))),read(e,t){const n=gn(t,d.timeouts.read),r=()=>kn(d,d.hosts.filter((e=>!!(e.accept&hn.Read))),e,n);if(!0!==(void 0!==n.cacheable?n.cacheable:e.cacheable))return r();const o={request:e,mappedRequestOptions:n,transporter:{queryParameters:d.queryParameters,headers:d.headers}};return d.responsesCache.get(o,(()=>d.requestsCache.get(o,(()=>d.requestsCache.set(o,r()).then((e=>Promise.all([d.requestsCache.delete(o),e])),(e=>Promise.all([d.requestsCache.delete(o),Promise.reject(e)]))).then((([e,t])=>t))))),{miss:e=>d.responsesCache.set(o,e)})},write:(e,t)=>kn(d,d.hosts.filter((e=>!!(e.accept&hn.Write))),e,gn(t,d.timeouts.write))};return d}({hosts:[{url:`${t}-dsn.algolia.net`,accept:hn.Read},{url:`${t}.algolia.net`,accept:hn.Write}].concat(dn([{url:`${t}-1.algolianet.com`},{url:`${t}-2.algolianet.com`},{url:`${t}-3.algolianet.com`}])),...e,headers:{...n.headers(),"content-type":"application/x-www-form-urlencoded",...e.headers},queryParameters:{...n.queryParameters(),...e.queryParameters}}),o={transporter:r,appId:t,addAlgoliaAgent(e,t){r.userAgent.add({segment:e,version:t})},clearCache:()=>Promise.all([r.requestsCache.clear(),r.responsesCache.clear()]).then((()=>{}))};return fn(o,e.methods)},An=e=>(t,n)=>t.method===Sn?e.transporter.read(t,n):e.transporter.write(t,n),Pn=e=>(t,n={})=>fn({transporter:e.transporter,appId:e.appId,indexName:t},n.methods),In=e=>(t,n)=>{const r=t.map((e=>({...e,params:jn(e.params||{})})));return e.transporter.read({method:xn,path:"1/indexes/*/queries",data:{requests:r},cacheable:!0},n)},Nn=e=>(t,n)=>Promise.all(t.map((t=>{const{facetName:r,facetQuery:o,...a}=t.params;return Pn(e)(t.indexName,{methods:{searchForFacetValues:Dn}}).searchForFacetValues(r,o,{...n,...a})}))),Rn=e=>(t,n,r)=>e.transporter.read({method:xn,path:pn("1/answers/%s/prediction",e.indexName),data:{query:t,queryLanguages:n},cacheable:!0},r),Ln=e=>(t,n)=>e.transporter.read({method:xn,path:pn("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},n),Dn=e=>(t,n,r)=>e.transporter.read({method:xn,path:pn("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:n},cacheable:!0},r),Mn=1,Fn=2,Bn=3;function zn(e,t,n){const r={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:e=>new Promise((t=>{const n=new XMLHttpRequest;n.open(e.method,e.url,!0),Object.keys(e.headers).forEach((t=>n.setRequestHeader(t,e.headers[t])));const r=(e,r)=>setTimeout((()=>{n.abort(),t({status:0,content:r,isTimedOut:!0})}),1e3*e),o=r(e.connectTimeout,"Connection timeout");let a;n.onreadystatechange=()=>{n.readyState>n.OPENED&&void 0===a&&(clearTimeout(o),a=r(e.responseTimeout,"Socket timeout"))},n.onerror=()=>{0===n.status&&(clearTimeout(o),clearTimeout(a),t({content:n.responseText||"Network request failed",status:n.status,isTimedOut:!1}))},n.onload=()=>{clearTimeout(o),clearTimeout(a),t({content:n.responseText,status:n.status,isTimedOut:!1})},n.send(e.data)}))},logger:(o=Bn,{debug:(e,t)=>(Mn>=o&&console.debug(e,t),Promise.resolve()),info:(e,t)=>(Fn>=o&&console.info(e,t),Promise.resolve()),error:(e,t)=>(console.error(e,t),Promise.resolve())}),responsesCache:un(),requestsCache:un({serializable:!1}),hostsCache:ln({caches:[cn({key:`4.19.1-${e}`}),un()]}),userAgent:En("4.19.1").add({segment:"Browser",version:"lite"}),authMode:mn.WithinQueryParameters};var o;return Tn({...r,...n,methods:{search:In,searchForFacetValues:Nn,multipleQueries:In,multipleSearchForFacetValues:Nn,customRequest:An,initIndex:e=>t=>Pn(e)(t,{methods:{search:Ln,searchForFacetValues:Dn,findAnswers:Rn}})}})}zn.version="4.19.1";var qn=["footer","searchBox"];function Un(e){var t=e.appId,n=e.apiKey,o=e.indexName,s=e.placeholder,u=void 0===s?"Search docs":s,d=e.searchParameters,f=e.maxResultsPerGroup,p=e.onClose,m=void 0===p?Kt:p,g=e.transformItems,h=void 0===g?Wt:g,b=e.hitComponent,y=void 0===b?_t:b,v=e.resultsFooterComponent,w=void 0===v?function(){return null}:v,S=e.navigator,x=e.initialScrollY,k=void 0===x?0:x,E=e.transformSearchClient,_=void 0===E?Wt:E,j=e.disableUserPersonalization,O=void 0!==j&&j,C=e.initialQuery,T=void 0===C?"":C,A=e.translations,P=void 0===A?{}:A,I=e.getMissingResultsUrl,N=e.insights,R=void 0!==N&&N,L=P.footer,D=P.searchBox,M=c(P,qn),F=l(r.useState({query:"",collections:[],completion:null,context:{},isOpen:!1,activeItemId:null,status:"idle"}),2),B=F[0],z=F[1],q=r.useRef(null),U=r.useRef(null),$=r.useRef(null),H=r.useRef(null),V=r.useRef(null),W=r.useRef(10),G=r.useRef("undefined"!=typeof window?window.getSelection().toString().slice(0,64):"").current,K=r.useRef(T||G).current,Y=function(e,t,n){return r.useMemo((function(){var r=zn(e,t);return r.addAlgoliaAgent("docsearch","3.6.1"),!1===/docsearch.js \(.*\)/.test(r.transporter.userAgent.value)&&r.addAlgoliaAgent("docsearch-react","3.6.1"),n(r)}),[e,t,n])}(t,n,_),Q=r.useRef(sn({key:"__DOCSEARCH_FAVORITE_SEARCHES__".concat(o),limit:10})).current,Z=r.useRef(sn({key:"__DOCSEARCH_RECENT_SEARCHES__".concat(o),limit:0===Q.getAll().length?7:4})).current,X=r.useCallback((function(e){if(!O){var t="content"===e.type?e.__docsearch_parent:e;t&&-1===Q.getAll().findIndex((function(e){return e.objectID===t.objectID}))&&Z.add(t)}}),[Q,Z,O]),J=r.useCallback((function(e){if(B.context.algoliaInsightsPlugin&&e.__autocomplete_id){var t=e,n={eventName:"Item Selected",index:t.__autocomplete_indexName,items:[t],positions:[e.__autocomplete_id],queryID:t.__autocomplete_queryID};B.context.algoliaInsightsPlugin.insights.clickedObjectIDsAfterSearch(n)}}),[B.context.algoliaInsightsPlugin]),ee=r.useMemo((function(){return St({id:"docsearch",defaultActiveItemId:0,placeholder:u,openOnFocus:!0,initialState:{query:K,context:{searchSuggestions:[]}},insights:R,navigator:S,onStateChange:function(e){z(e.state)},getSources:function(e){var r=e.query,s=e.state,i=e.setContext,c=e.setStatus;if(!r)return O?[]:[{sourceId:"recentSearches",onSelect:function(e){var t=e.item,n=e.event;X(t),Gt(n)||m()},getItemUrl:function(e){return e.item.url},getItems:function(){return Z.getAll()}},{sourceId:"favoriteSearches",onSelect:function(e){var t=e.item,n=e.event;X(t),Gt(n)||m()},getItemUrl:function(e){return e.item.url},getItems:function(){return Q.getAll()}}];var l=Boolean(R);return Y.search([{query:r,indexName:o,params:a({attributesToRetrieve:["hierarchy.lvl0","hierarchy.lvl1","hierarchy.lvl2","hierarchy.lvl3","hierarchy.lvl4","hierarchy.lvl5","hierarchy.lvl6","content","type","url"],attributesToSnippet:["hierarchy.lvl1:".concat(W.current),"hierarchy.lvl2:".concat(W.current),"hierarchy.lvl3:".concat(W.current),"hierarchy.lvl4:".concat(W.current),"hierarchy.lvl5:".concat(W.current),"hierarchy.lvl6:".concat(W.current),"content:".concat(W.current)],snippetEllipsisText:"\u2026",highlightPreTag:"",highlightPostTag:"",hitsPerPage:20,clickAnalytics:l},d)}]).catch((function(e){throw"RetryError"===e.name&&c("error"),e})).then((function(e){var r=e.results[0],c=r.hits,u=r.nbHits,d=Vt(c,(function(e){return Zt(e)}),f);s.context.searchSuggestions.length0&&(re(),V.current&&V.current.focus())}),[K,re]),r.useEffect((function(){function e(){if(U.current){var e=.01*window.innerHeight;U.current.style.setProperty("--docsearch-vh","".concat(e,"px"))}}return e(),window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}),[]),r.createElement("div",i({ref:q},ne({"aria-expanded":!0}),{className:["DocSearch","DocSearch-Container","stalled"===B.status&&"DocSearch-Container--Stalled","error"===B.status&&"DocSearch-Container--Errored"].filter(Boolean).join(" "),role:"button",tabIndex:0,onMouseDown:function(e){e.target===e.currentTarget&&m()}}),r.createElement("div",{className:"DocSearch-Modal",ref:U},r.createElement("header",{className:"DocSearch-SearchBar",ref:$},r.createElement(on,i({},ee,{state:B,autoFocus:0===K.length,inputRef:V,isFromSelection:Boolean(K)&&K===G,translations:D,onClose:m}))),r.createElement("div",{className:"DocSearch-Dropdown",ref:H},r.createElement(nn,i({},ee,{indexName:o,state:B,hitComponent:y,resultsFooterComponent:w,disableUserPersonalization:O,recentSearches:Z,favoriteSearches:Q,inputRef:V,translations:M,getMissingResultsUrl:I,onItemClick:function(e,t){J(e),X(e),Gt(t)||m()}}))),r.createElement("footer",{className:"DocSearch-Footer"},r.createElement(Et,{translations:L}))))}function $n(e){var t=e.isOpen,n=e.onOpen,o=e.onClose,a=e.onInput,s=e.searchButtonRef;r.useEffect((function(){function e(e){var r;(27===e.keyCode&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?o():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),s&&s.current===document.activeElement&&a&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&a(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,o,a,s])}},2413:(e,t,n)=>{"use strict";n.d(t,{A:()=>f});n(6540);var r=n(3259),o=n.n(r),a=n(4054);const s={"03802b97":[()=>n.e(1012).then(n.t.bind(n,5795,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-marketing-cloud-personalization-5ad.json",5795],"06bea203":[()=>Promise.all([n.e(1869),n.e(8632)]).then(n.bind(n,7531)),"@site/sites/privacy.mdx",7531],"0a4e9b8a":[()=>n.e(6239).then(n.t.bind(n,9222,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-java-script-df8.json",9222],"0a722898":[()=>n.e(1652).then(n.t.bind(n,6569,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-crm-b85.json",6569],"0ae20921":[()=>Promise.all([n.e(1869),n.e(4817)]).then(n.bind(n,5258)),"@site/docs/config/sfmc-contact-deletion.mdx",5258],"0b0448dc":[()=>n.e(6698).then(n.t.bind(n,2556,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-category-ideas-dad.json",2556],"0cb3f831":[()=>Promise.all([n.e(1869),n.e(1691)]).then(n.bind(n,4759)),"@site/docs/js/js-loops.mdx",4759],"0d39e944":[()=>n.e(7305).then(n.t.bind(n,3785,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-snippet-0b6.json",3785],11547437:[()=>Promise.all([n.e(1869),n.e(9821)]).then(n.bind(n,6987)),"@site/docs/config/sfmc-licence-limits.mdx",6987],"11b43341":[()=>n.e(2256).then(n.t.bind(n,5293,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-7fc.json",5293],"1328d02f":[()=>Promise.all([n.e(1869),n.e(9213)]).then(n.bind(n,2192)),"@site/docs/sql/sfmc-sql-date-functions.mdx",2192],"139f0dd3":[()=>Promise.all([n.e(1869),n.e(2305)]).then(n.bind(n,7309)),"@site/sites/toolset.mdx",7309],"13cedcd3":[()=>n.e(5679).then(n.t.bind(n,9749,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-faq-850.json",9749],"13f9d961":[()=>Promise.all([n.e(1869),n.e(7458)]).then(n.bind(n,2923)),"@site/docs/config/sfmc-mcc-integration-patterns.mdx",2923],"14add631":[()=>Promise.all([n.e(1869),n.e(9125)]).then(n.bind(n,4776)),"@site/docs/interaction-studio/mcp-catalog-architecture.mdx",4776],"14eb3368":[()=>Promise.all([n.e(1869),n.e(6969)]).then(n.bind(n,7449)),"@theme/DocCategoryGeneratedIndexPage",7449],"15878b2f":[()=>Promise.all([n.e(1869),n.e(4492)]).then(n.bind(n,1860)),"@site/docs/webinars/sfmc-webinar-architecting-web-solutions.mdx",1860],"16a1f048":[()=>n.e(9658).then(n.t.bind(n,2687,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-ampscript-629.json",2687],17896441:[()=>Promise.all([n.e(1869),n.e(8401)]).then(n.bind(n,7952)),"@theme/DocItem",7952],"1843ef45":[()=>Promise.all([n.e(1869),n.e(7475)]).then(n.bind(n,2208)),"@site/docs/js/js-if-and-switch.mdx",2208],"18f12793":[()=>Promise.all([n.e(1869),n.e(4406)]).then(n.bind(n,2058)),"@site/docs/sql/snippets/sfmc-sql-debugging-value-length.mdx",2058],"1a4e3797":[()=>Promise.all([n.e(1869),n.e(2138)]).then(n.bind(n,5202)),"@theme/SearchPage",5202],"1a945320":[()=>n.e(1880).then(n.t.bind(n,6330,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-personalization-bb2.json",6330],"1ad5d13a":[()=>Promise.all([n.e(1869),n.e(4649)]).then(n.bind(n,2094)),"@site/sites/faq/how-to-get-sf-certification-vouchers.mdx",2094],"1b5b4d1e":[()=>n.e(6313).then(n.t.bind(n,8714,19)),"@generated/docusaurus-plugin-content-docs/sites/__plugin.json",8714],"1c5265ab":[()=>n.e(2592).then(n.t.bind(n,2019,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-serverside-code-eb7.json",2019],"20386bb8":[()=>n.e(5346).then(n.t.bind(n,1052,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-setup-951.json",1052],"20e039ae":[()=>Promise.all([n.e(1869),n.e(672)]).then(n.bind(n,4288)),"@site/docs/sql/sfmc-sql-from.mdx",4288],21423537:[()=>n.e(1352).then(n.t.bind(n,9489,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-sfmc-sql-7c2.json",9489],"22145d1a":[()=>Promise.all([n.e(1869),n.e(7281)]).then(n.bind(n,6395)),"@site/docs/ssjs/ssjs-loops.mdx",6395],"240325d0":[()=>Promise.all([n.e(1869),n.e(6134),n.e(2429)]).then(n.bind(n,7469)),"@site/docs/interaction-studio/mcp-serverside-code-basics.mdx",7469],"2b6eeb7d":[()=>n.e(680).then(n.t.bind(n,7476,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-data-management-f2d.json",7476],"2cf43088":[()=>Promise.all([n.e(1869),n.e(673)]).then(n.bind(n,275)),"@site/docs/ssjs/snippets/sfmc-cloud-page-apps.mdx",275],"2e2f252f":[()=>Promise.all([n.e(1869),n.e(9551)]).then(n.bind(n,4485)),"@site/sites/ideas/marketing-cloud-ideas.mdx",4485],"30084dac":[()=>Promise.all([n.e(1869),n.e(1870)]).then(n.bind(n,4143)),"@site/docs/sql/sfmc-sql-aggregate-functions.mdx",4143],"30f53c3b":[()=>n.e(4736).then(n.t.bind(n,7063,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-sms-3ab.json",7063],"32c8b40e":[()=>n.e(7274).then(n.t.bind(n,3127,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-integration-24e.json",3127],"3365a9e9":[()=>Promise.all([n.e(1869),n.e(2290)]).then(n.bind(n,9604)),"@site/docs/config/sfmc-behavioral-triggers.mdx",9604],"33ffb019":[()=>Promise.all([n.e(1869),n.e(1825)]).then(n.bind(n,6136)),"@site/docs/docs-and-snippets.mdx",6136],"34e3d3b2":[()=>n.e(3305).then(n.t.bind(n,9956,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-marketing-cloud-8c5.json",9956],"36c171c8":[()=>n.e(9393).then(n.t.bind(n,2656,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-e14.json",2656],"3720c009":[()=>Promise.all([n.e(1869),n.e(4787)]).then(n.bind(n,6862)),"@theme/DocTagsListPage",6862],"39beba1b":[()=>n.e(5258).then(n.t.bind(n,7003,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-performance-44c.json",7003],"40386ff6":[()=>n.e(4078).then(n.t.bind(n,6394,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-einstein-656.json",6394],"407fe916":[()=>Promise.all([n.e(1869),n.e(9459)]).then(n.bind(n,4244)),"@site/docs/js/snippets/tailor-with-data.mdx",4244],"4220d504":[()=>n.e(4726).then(n.t.bind(n,7686,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-js-snippets-dd1.json",7686],"429ee4f3":[()=>n.e(9745).then(n.t.bind(n,1695,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-behavioral-triggers-361.json",1695],"4604a801":[()=>n.e(5727).then(n.t.bind(n,7196,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-mc-personalization-dbf.json",7196],"4d6aece4":[()=>Promise.all([n.e(1869),n.e(135)]).then(n.bind(n,747)),"@site/docs/webinars/sfmc-webinar-cloud-page-apps.mdx",747],"4fb0cc17":[()=>n.e(4681).then(n.t.bind(n,220,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-type-script-ec0.json",220],"509f2ea4":[()=>Promise.all([n.e(1869),n.e(8705)]).then(n.bind(n,7299)),"@site/docs/sql/sfmc-sql-where.mdx",7299],"566b4bf5":[()=>n.e(8519).then(n.t.bind(n,1762,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-email-d86.json",1762],"58d9bd12":[()=>n.e(9954).then(n.t.bind(n,18,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-ampscript-snippets-102.json",18],"5e95c892":[()=>n.e(9647).then(n.bind(n,3124)),"@theme/DocsRoot",3124],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,4784)),"@generated/docusaurus.config",4784],"5ee690fc":[()=>Promise.all([n.e(1869),n.e(6134),n.e(9646)]).then(n.bind(n,4916)),"@site/docs/sql/sfmc-sql-join.mdx",4916],"5ee7ecad":[()=>Promise.all([n.e(1869),n.e(2330)]).then(n.bind(n,3356)),"@site/docs/sql/sfmc-sql-string-functions.mdx",3356],"5f4f370c":[()=>n.e(5089).then(n.t.bind(n,499,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-best-practice-f61.json",499],"612d51b5":[()=>Promise.all([n.e(1869),n.e(5627)]).then(n.bind(n,3144)),"@site/docs/config/sfmc-mobile-connect-data-views.mdx",3144],"67a57efa":[()=>Promise.all([n.e(1869),n.e(183)]).then(n.bind(n,4884)),"@site/docs/ssjs/ssjs-if-and-switch.mdx",4884],"6d83c2a5":[()=>Promise.all([n.e(1869),n.e(7315)]).then(n.bind(n,9897)),"@site/docs/sql/sfmc-sql-like.mdx",9897],"6e1c7d40":[()=>n.e(3585).then(n.t.bind(n,330,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-app-exchange-dd5.json",330],"6f161a02":[()=>n.e(6982).then(n.t.bind(n,3934,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-sql-snippets-94c.json",3934],"6f8e0829":[()=>n.e(6077).then(n.t.bind(n,8914,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-webinar-d7a.json",8914],"71d251b8":[()=>n.e(8177).then(n.t.bind(n,4820,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-sql-ce4.json",4820],"730e2315":[()=>n.e(2703).then(n.t.bind(n,7297,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-journey-8b5.json",7297],"73f68733":[()=>n.e(5492).then(n.t.bind(n,9491,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-configuration-acc.json",9491],"772c8612":[()=>Promise.all([n.e(1869),n.e(3595)]).then(n.bind(n,2798)),"@site/sites/licence.mdx",2798],"7827587b":[()=>Promise.all([n.e(1869),n.e(6959)]).then(n.bind(n,280)),"@site/docs/ssjs/snippets/ampscript-in-ssjs.mdx",280],"78a76a15":[()=>n.e(2767).then(n.t.bind(n,5043,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-mc-personalization-snippets-47e.json",5043],"78d97820":[()=>n.e(1628).then(n.t.bind(n,8812,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-ssjs-2c7.json",8812],"7a9e8c54":[()=>n.e(2933).then(n.t.bind(n,7791,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-api-a71.json",7791],"7e37f256":[()=>n.e(2072).then(n.t.bind(n,1351,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-ssjs-5cd.json",1351],"7e9ef75f":[()=>n.e(685).then(n.t.bind(n,7547,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-best-practice-c9a.json",7547],"7f3cd917":[()=>Promise.all([n.e(1869),n.e(7571)]).then(n.bind(n,3183)),"@site/docs/js/snippets/engage-with-countdown.mdx",3183],"7f9f5c99":[()=>Promise.all([n.e(1869),n.e(6419)]).then(n.bind(n,2532)),"@site/docs/config/sfmc-system-data-views.mdx",2532],"81fb7942":[()=>Promise.all([n.e(1869),n.e(1464)]).then(n.bind(n,3819)),"@site/sites/faq/how-to-get-sfmc-hands-on-experience.mdx",3819],"83a2c636":[()=>n.e(7489).then(n.t.bind(n,4671,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-cloud-page-4db.json",4671],"8dfb128c":[()=>Promise.all([n.e(1869),n.e(9525)]).then(n.bind(n,8116)),"@site/sites/ideas/mc-personalization-ideas.mdx",8116],"8fc0bb6c":[()=>n.e(245).then(n.t.bind(n,8266,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-interaction-studio-458.json",8266],"8feba3b6":[()=>n.e(6416).then(n.t.bind(n,1086,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-analytics-0c7.json",1086],"929714a5":[()=>Promise.all([n.e(1869),n.e(3823)]).then(n.bind(n,4519)),"@site/docs/interaction-studio/mcp-serverside-code-context.mdx",4519],"92cda9bf":[()=>Promise.all([n.e(1869),n.e(5097)]).then(n.bind(n,9360)),"@site/docs/ssjs/debugging-ssjs.mdx",9360],"937990e1":[()=>Promise.all([n.e(1869),n.e(354)]).then(n.bind(n,359)),"@site/docs/interaction-studio/mcp-serverside-code-properties.mdx",359],"97eb2af9":[()=>n.e(5430).then(n.t.bind(n,8952,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-eloqua-906.json",8952],"994a44f5":[()=>n.e(6927).then(n.t.bind(n,4461,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-users-234.json",4461],"9be7a4ef":[()=>Promise.all([n.e(1869),n.e(1428)]).then(n.bind(n,8054)),"@site/docs/ampscript/ampscript-style-guide.mdx",8054],a1a4ce5c:[()=>n.e(966).then(n.t.bind(n,4069,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-ssjs-snippets-40f.json",4069],a1fce12d:[()=>n.e(3932).then(n.t.bind(n,1782,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-javascript-303.json",1782],a3e4529f:[()=>n.e(5992).then(n.t.bind(n,4921,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-deliverability-b1c.json",4921],a7456010:[()=>n.e(1235).then(n.t.bind(n,8552,19)),"@generated/docusaurus-plugin-content-pages/default/__plugin.json",8552],a7bd4aaa:[()=>n.e(7098).then(n.bind(n,2881)),"@theme/DocVersionRoot",2881],a8b77297:[()=>Promise.all([n.e(1869),n.e(8330)]).then(n.bind(n,337)),"@site/docs/config/sfmc-code-resource.mdx",337],a94703ab:[()=>Promise.all([n.e(1869),n.e(9048)]).then(n.bind(n,8001)),"@theme/DocRoot",8001],aaff29e3:[()=>n.e(4862).then(n.t.bind(n,7266,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-marketing-cloud-042.json",7266],aba21aa0:[()=>n.e(5742).then(n.t.bind(n,7093,19)),"@generated/docusaurus-plugin-content-docs/default/__plugin.json",7093],aeba84fb:[()=>Promise.all([n.e(1869),n.e(4894)]).then(n.bind(n,6771)),"@site/docs/zen-of-sfmc.mdx",6771],af519e1f:[()=>n.e(5327).then(n.t.bind(n,1602,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-a68.json",1602],af87a3ae:[()=>n.e(3955).then(n.t.bind(n,7248,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-automation-164.json",7248],b2e73532:[()=>n.e(3056).then(n.t.bind(n,6924,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-app-c5a.json",6924],b39e9a29:[()=>Promise.all([n.e(1869),n.e(441)]).then(n.bind(n,56)),"@site/docs/sql/sfmc-sql-select.mdx",56],b4a0624b:[()=>n.e(3880).then(n.t.bind(n,5893,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-amp-script-0bd.json",5893],b52e5d8d:[()=>Promise.all([n.e(1869),n.e(6412)]).then(n.bind(n,6122)),"@site/docs/config/sfmc-features-on-demand.mdx",6122],b840d82f:[()=>Promise.all([n.e(1869),n.e(3657)]).then(n.bind(n,3757)),"@site/docs/sql/sfmc-sql-basics.mdx",3757],b84a6020:[()=>Promise.all([n.e(1869),n.e(7060)]).then(n.bind(n,7781)),"@site/docs/ssjs/snippets/ssjs-mobileconnect-phone-change.mdx",7781],bb42d0c1:[()=>Promise.all([n.e(1869),n.e(7261)]).then(n.bind(n,8498)),"@site/docs/webinars/sfmc-webinar-salesforce-data-in-journey-builder.mdx",8498],bb5d57b6:[()=>Promise.all([n.e(1869),n.e(116)]).then(n.bind(n,527)),"@site/docs/sql/sfmc-sql-numeric-functions.mdx",527],beb9716f:[()=>Promise.all([n.e(1869),n.e(4815)]).then(n.bind(n,4614)),"@site/sites/newsletter.mdx",4614],bfce8808:[()=>n.e(7291).then(n.t.bind(n,952,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-sfmc-config-548.json",952],c141421f:[()=>n.e(957).then(n.t.bind(n,936,19)),"@generated/docusaurus-theme-search-algolia/default/__plugin.json",936],c4f5d8e4:[()=>Promise.all([n.e(1869),n.e(2634)]).then(n.bind(n,2221)),"@site/src/pages/index.js",2221],c5a49354:[()=>n.e(8691).then(n.t.bind(n,1485,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-personalisation-20f.json",1485],c64b8421:[()=>Promise.all([n.e(1869),n.e(1833)]).then(n.bind(n,7068)),"@site/docs/sql/sfmc-sql-case.mdx",7068],c8a2287d:[()=>Promise.all([n.e(1869),n.e(6134),n.e(9212)]).then(n.bind(n,4824)),"@site/docs/config/sfmc-appexchange-solutions.mdx",4824],cc887191:[()=>n.e(7435).then(n.t.bind(n,3721,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-style-guide-4cb.json",3721],cf3dc04b:[()=>n.e(6838).then(n.t.bind(n,2751,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-category-faq-30a.json",2751],d44a7d50:[()=>Promise.all([n.e(1869),n.e(6134),n.e(9136)]).then(n.bind(n,4494)),"@site/docs/sql/snippets/sfmc-sql-debugging-email-sends.mdx",4494],d4ed38e0:[()=>Promise.all([n.e(1869),n.e(9854)]).then(n.bind(n,6708)),"@site/docs/sql/sfmc-sql-conversion-functions.mdx",6708],d5687ba7:[()=>Promise.all([n.e(1869),n.e(5319)]).then(n.bind(n,7234)),"@site/docs/ssjs/ssjs-style-guide.mdx",7234],dc8b40ff:[()=>Promise.all([n.e(1869),n.e(6306)]).then(n.bind(n,9929)),"@site/docs/ssjs/snippets/ssjs-script-template.mdx",9929],ded03d03:[()=>n.e(8960).then(n.t.bind(n,4572,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-data-extensions-ec7.json",4572],ded77f33:[()=>n.e(9176).then(n.t.bind(n,9210,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-interaction-studio-8b1.json",9210],df203c0f:[()=>Promise.all([n.e(1869),n.e(4279)]).then(n.bind(n,6958)),"@theme/DocTagDocListPage",6958],e5fc05e6:[()=>Promise.all([n.e(1869),n.e(5504)]).then(n.bind(n,3187)),"@site/docs/sql/sfmc-sql-null-functions.mdx",3187],e65d7673:[()=>n.e(3832).then(n.t.bind(n,4008,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-marketing-cloud-personalization-a73.json",4008],e81bfcdf:[()=>n.e(9934).then(n.t.bind(n,6154,19)),"@generated/docusaurus-plugin-content-docs/sites/p/sites-tags-e57.json",6154],ec6dc5c4:[()=>Promise.all([n.e(1869),n.e(8280)]).then(n.bind(n,4087)),"@site/docs/js/snippets/export-import-document-sfmc-roles.mdx",4087],ecbe7f2c:[()=>Promise.all([n.e(1869),n.e(5718)]).then(n.bind(n,7674)),"@site/docs/sql/sfmc-sql-style-guide.mdx",7674],ecd0154e:[()=>Promise.all([n.e(1869),n.e(9304)]).then(n.bind(n,3226)),"@site/docs/js/js-dom.mdx",3226],edb10261:[()=>Promise.all([n.e(1869),n.e(302)]).then(n.bind(n,5622)),"@site/docs/webinars/sfmc-webinar-account-architecture.mdx",5622],edc70957:[()=>n.e(1147).then(n.t.bind(n,3147,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-category-sfmc-webinars-1e1.json",3147],f2cf2415:[()=>n.e(2208).then(n.t.bind(n,5238,19)),"@generated/docusaurus-plugin-content-docs/default/p/docs-tags-debugging-3eb.json",5238],f564aeae:[()=>Promise.all([n.e(1869),n.e(630)]).then(n.bind(n,937)),"@site/docs/config/sfmc-enhanced-send-log.mdx",937],fd9368c3:[()=>Promise.all([n.e(1869),n.e(1873)]).then(n.bind(n,4960)),"@site/docs/interaction-studio/snippets/mcp-catalog-etl-metadata-viewer.mdx",4960],fe4d0c3d:[()=>Promise.all([n.e(1869),n.e(5702)]).then(n.bind(n,9226)),"@site/docs/interaction-studio/mcp-open-time-email.mdx",9226],ff6cdf17:[()=>Promise.all([n.e(1869),n.e(5876)]).then(n.bind(n,8080)),"@site/docs/ssjs/ssjs-vs-ampscript-performance.mdx",8080]};var i=n(4848);function c(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,i.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,i.jsx)("p",{children:String(t)}),(0,i.jsx)("div",{children:(0,i.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,i.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,i.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,i.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,i.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,i.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,i.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,i.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,i.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,i.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,i.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,i.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,i.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,i.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var l=n(1604),u=n(3363);function d(e,t){if("*"===e)return o()({loading:c,loader:()=>n.e(2560).then(n.bind(n,2560)),modules:["@theme/NotFound"],webpack:()=>[2560],render(e,t){const n=e.default;return(0,i.jsx)(u.W,{value:{plugin:{name:"native",id:"default"}},children:(0,i.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},f=[],p=[],m=(0,l.A)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=s[n];r&&(d[t]=r[0],f.push(r[1]),p.push(r[2]))})),o().Map({loading:c,loader:d,modules:f,webpack:()=>p,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let s=o;const i=n.split(".");i.slice(0,-1).forEach((e=>{s=s[e]})),s[i[i.length-1]]=a}));const a=o.__comp;delete o.__comp;const s=o.__context;delete o.__context;const c=o.__props;return delete o.__props,(0,i.jsx)(u.W,{value:s,children:(0,i.jsx)(a,{...o,...c,...n})})}})}const f=[{path:"/search/",component:d("/search/","21e"),exact:!0},{path:"/docs/",component:d("/docs/","221"),routes:[{path:"/docs/",component:d("/docs/","8b3"),routes:[{path:"/docs/tags/",component:d("/docs/tags/","dc9"),exact:!0},{path:"/docs/tags/amp-script/",component:d("/docs/tags/amp-script/","023"),exact:!0},{path:"/docs/tags/analytics/",component:d("/docs/tags/analytics/","f8d"),exact:!0},{path:"/docs/tags/api/",component:d("/docs/tags/api/","670"),exact:!0},{path:"/docs/tags/app-exchange/",component:d("/docs/tags/app-exchange/","037"),exact:!0},{path:"/docs/tags/app/",component:d("/docs/tags/app/","bdd"),exact:!0},{path:"/docs/tags/automation/",component:d("/docs/tags/automation/","05e"),exact:!0},{path:"/docs/tags/behavioral-triggers/",component:d("/docs/tags/behavioral-triggers/","a80"),exact:!0},{path:"/docs/tags/best-practice/",component:d("/docs/tags/best-practice/","9d4"),exact:!0},{path:"/docs/tags/cloud-page/",component:d("/docs/tags/cloud-page/","28d"),exact:!0},{path:"/docs/tags/configuration/",component:d("/docs/tags/configuration/","6b3"),exact:!0},{path:"/docs/tags/crm/",component:d("/docs/tags/crm/","48a"),exact:!0},{path:"/docs/tags/data-extensions/",component:d("/docs/tags/data-extensions/","a40"),exact:!0},{path:"/docs/tags/data-management/",component:d("/docs/tags/data-management/","259"),exact:!0},{path:"/docs/tags/debugging/",component:d("/docs/tags/debugging/","1f2"),exact:!0},{path:"/docs/tags/deliverability/",component:d("/docs/tags/deliverability/","c08"),exact:!0},{path:"/docs/tags/einstein/",component:d("/docs/tags/einstein/","7a1"),exact:!0},{path:"/docs/tags/eloqua/",component:d("/docs/tags/eloqua/","bf9"),exact:!0},{path:"/docs/tags/email/",component:d("/docs/tags/email/","599"),exact:!0},{path:"/docs/tags/integration/",component:d("/docs/tags/integration/","07b"),exact:!0},{path:"/docs/tags/interaction-studio/",component:d("/docs/tags/interaction-studio/","555"),exact:!0},{path:"/docs/tags/java-script/",component:d("/docs/tags/java-script/","5e7"),exact:!0},{path:"/docs/tags/journey/",component:d("/docs/tags/journey/","60b"),exact:!0},{path:"/docs/tags/marketing-cloud-personalization/",component:d("/docs/tags/marketing-cloud-personalization/","5b4"),exact:!0},{path:"/docs/tags/marketing-cloud/",component:d("/docs/tags/marketing-cloud/","897"),exact:!0},{path:"/docs/tags/performance/",component:d("/docs/tags/performance/","38f"),exact:!0},{path:"/docs/tags/personalisation/",component:d("/docs/tags/personalisation/","c28"),exact:!0},{path:"/docs/tags/setup/",component:d("/docs/tags/setup/","4c7"),exact:!0},{path:"/docs/tags/sms/",component:d("/docs/tags/sms/","353"),exact:!0},{path:"/docs/tags/snippet/",component:d("/docs/tags/snippet/","1b0"),exact:!0},{path:"/docs/tags/sql/",component:d("/docs/tags/sql/","b2e"),exact:!0},{path:"/docs/tags/ssjs/",component:d("/docs/tags/ssjs/","6c3"),exact:!0},{path:"/docs/tags/style-guide/",component:d("/docs/tags/style-guide/","1d7"),exact:!0},{path:"/docs/tags/type-script/",component:d("/docs/tags/type-script/","00a"),exact:!0},{path:"/docs/tags/users/",component:d("/docs/tags/users/","588"),exact:!0},{path:"/docs/tags/webinar/",component:d("/docs/tags/webinar/","0f3"),exact:!0},{path:"/docs/",component:d("/docs/","43e"),routes:[{path:"/docs/",component:d("/docs/","598"),exact:!0,sidebar:"docs"},{path:"/docs/ampscript/ampscript-style-guide/",component:d("/docs/ampscript/ampscript-style-guide/","e38"),exact:!0,sidebar:"docs"},{path:"/docs/category/-ampscript-snippets/",component:d("/docs/category/-ampscript-snippets/","7e6"),exact:!0,sidebar:"docs"},{path:"/docs/category/-js-snippets/",component:d("/docs/category/-js-snippets/","9a8"),exact:!0,sidebar:"docs"},{path:"/docs/category/-mc-personalization-snippets/",component:d("/docs/category/-mc-personalization-snippets/","f7a"),exact:!0,sidebar:"docs"},{path:"/docs/category/-serverside-code/",component:d("/docs/category/-serverside-code/","0c8"),exact:!0,sidebar:"docs"},{path:"/docs/category/-sql-snippets/",component:d("/docs/category/-sql-snippets/","6da"),exact:!0,sidebar:"docs"},{path:"/docs/category/-ssjs-snippets/",component:d("/docs/category/-ssjs-snippets/","50a"),exact:!0,sidebar:"docs"},{path:"/docs/category/ampscript/",component:d("/docs/category/ampscript/","5ce"),exact:!0,sidebar:"docs"},{path:"/docs/category/javascript/",component:d("/docs/category/javascript/","116"),exact:!0,sidebar:"docs"},{path:"/docs/category/mc-personalization/",component:d("/docs/category/mc-personalization/","a2b"),exact:!0,sidebar:"docs"},{path:"/docs/category/sfmc-config/",component:d("/docs/category/sfmc-config/","639"),exact:!0,sidebar:"docs"},{path:"/docs/category/sfmc-sql/",component:d("/docs/category/sfmc-sql/","292"),exact:!0,sidebar:"docs"},{path:"/docs/category/sfmc-webinars/",component:d("/docs/category/sfmc-webinars/","3b1"),exact:!0,sidebar:"webinars"},{path:"/docs/category/ssjs/",component:d("/docs/category/ssjs/","177"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-appexchange-solutions/",component:d("/docs/config/sfmc-appexchange-solutions/","024"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-behavioral-triggers/",component:d("/docs/config/sfmc-behavioral-triggers/","603"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-code-resource/",component:d("/docs/config/sfmc-code-resource/","741"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-contact-deletion/",component:d("/docs/config/sfmc-contact-deletion/","616"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-enhanced-send-log/",component:d("/docs/config/sfmc-enhanced-send-log/","e1c"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-features-on-demand/",component:d("/docs/config/sfmc-features-on-demand/","c52"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-licence-limits/",component:d("/docs/config/sfmc-licence-limits/","e7a"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-mcc-integration-patterns/",component:d("/docs/config/sfmc-mcc-integration-patterns/","f66"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-mobile-connect-data-views/",component:d("/docs/config/sfmc-mobile-connect-data-views/","9c8"),exact:!0,sidebar:"docs"},{path:"/docs/config/sfmc-system-data-views/",component:d("/docs/config/sfmc-system-data-views/","90d"),exact:!0,sidebar:"docs"},{path:"/docs/interaction-studio/mcp-catalog-architecture/",component:d("/docs/interaction-studio/mcp-catalog-architecture/","4d4"),exact:!0,sidebar:"docs"},{path:"/docs/interaction-studio/mcp-open-time-email/",component:d("/docs/interaction-studio/mcp-open-time-email/","711"),exact:!0,sidebar:"docs"},{path:"/docs/interaction-studio/mcp-serverside-code-basics/",component:d("/docs/interaction-studio/mcp-serverside-code-basics/","b1f"),exact:!0,sidebar:"docs"},{path:"/docs/interaction-studio/mcp-serverside-code-context/",component:d("/docs/interaction-studio/mcp-serverside-code-context/","4be"),exact:!0,sidebar:"docs"},{path:"/docs/interaction-studio/mcp-serverside-code-properties/",component:d("/docs/interaction-studio/mcp-serverside-code-properties/","4d2"),exact:!0,sidebar:"docs"},{path:"/docs/interaction-studio/snippets/mcp-catalog-etl-metadata-viewer/",component:d("/docs/interaction-studio/snippets/mcp-catalog-etl-metadata-viewer/","9b5"),exact:!0,sidebar:"docs"},{path:"/docs/js/js-dom/",component:d("/docs/js/js-dom/","004"),exact:!0,sidebar:"docs"},{path:"/docs/js/js-if-and-switch/",component:d("/docs/js/js-if-and-switch/","168"),exact:!0,sidebar:"docs"},{path:"/docs/js/js-loops/",component:d("/docs/js/js-loops/","e4b"),exact:!0,sidebar:"docs"},{path:"/docs/js/snippets/engage-with-countdown/",component:d("/docs/js/snippets/engage-with-countdown/","1b4"),exact:!0,sidebar:"docs"},{path:"/docs/js/snippets/export-import-document-sfmc-roles/",component:d("/docs/js/snippets/export-import-document-sfmc-roles/","4b7"),exact:!0,sidebar:"docs"},{path:"/docs/js/snippets/tailor-with-data/",component:d("/docs/js/snippets/tailor-with-data/","34d"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-aggregate-functions/",component:d("/docs/sql/sfmc-sql-aggregate-functions/","53e"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-basics/",component:d("/docs/sql/sfmc-sql-basics/","c2d"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-case/",component:d("/docs/sql/sfmc-sql-case/","7af"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-conversion-functions/",component:d("/docs/sql/sfmc-sql-conversion-functions/","35d"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-date-functions/",component:d("/docs/sql/sfmc-sql-date-functions/","db4"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-from/",component:d("/docs/sql/sfmc-sql-from/","ca8"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-join/",component:d("/docs/sql/sfmc-sql-join/","c2f"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-like/",component:d("/docs/sql/sfmc-sql-like/","abc"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-null-functions/",component:d("/docs/sql/sfmc-sql-null-functions/","324"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-numeric-functions/",component:d("/docs/sql/sfmc-sql-numeric-functions/","2a2"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-select/",component:d("/docs/sql/sfmc-sql-select/","2e8"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-string-functions/",component:d("/docs/sql/sfmc-sql-string-functions/","57b"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-style-guide/",component:d("/docs/sql/sfmc-sql-style-guide/","95f"),exact:!0,sidebar:"docs"},{path:"/docs/sql/sfmc-sql-where/",component:d("/docs/sql/sfmc-sql-where/","03d"),exact:!0,sidebar:"docs"},{path:"/docs/sql/snippets/sfmc-sql-debugging-email-sends/",component:d("/docs/sql/snippets/sfmc-sql-debugging-email-sends/","217"),exact:!0,sidebar:"docs"},{path:"/docs/sql/snippets/sfmc-sql-debugging-value-length/",component:d("/docs/sql/snippets/sfmc-sql-debugging-value-length/","68b"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/debugging-ssjs/",component:d("/docs/ssjs/debugging-ssjs/","bea"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/snippets/ampscript-in-ssjs/",component:d("/docs/ssjs/snippets/ampscript-in-ssjs/","367"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/snippets/sfmc-cloud-page-apps/",component:d("/docs/ssjs/snippets/sfmc-cloud-page-apps/","09e"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/snippets/ssjs-mobileconnect-phone-change/",component:d("/docs/ssjs/snippets/ssjs-mobileconnect-phone-change/","997"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/snippets/ssjs-script-template/",component:d("/docs/ssjs/snippets/ssjs-script-template/","55d"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/ssjs-if-and-switch/",component:d("/docs/ssjs/ssjs-if-and-switch/","d8c"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/ssjs-loops/",component:d("/docs/ssjs/ssjs-loops/","0de"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/ssjs-style-guide/",component:d("/docs/ssjs/ssjs-style-guide/","427"),exact:!0,sidebar:"docs"},{path:"/docs/ssjs/ssjs-vs-ampscript-performance/",component:d("/docs/ssjs/ssjs-vs-ampscript-performance/","164"),exact:!0,sidebar:"docs"},{path:"/docs/webinars/sfmc-webinar-account-architecture/",component:d("/docs/webinars/sfmc-webinar-account-architecture/","282"),exact:!0,sidebar:"webinars"},{path:"/docs/webinars/sfmc-webinar-architecting-web-solutions/",component:d("/docs/webinars/sfmc-webinar-architecting-web-solutions/","a3c"),exact:!0,sidebar:"webinars"},{path:"/docs/webinars/sfmc-webinar-cloud-page-apps/",component:d("/docs/webinars/sfmc-webinar-cloud-page-apps/","4de"),exact:!0,sidebar:"webinars"},{path:"/docs/webinars/sfmc-webinar-salesforce-data-in-journey-builder/",component:d("/docs/webinars/sfmc-webinar-salesforce-data-in-journey-builder/","34b"),exact:!0,sidebar:"webinars"},{path:"/docs/zen-of-sfmc/",component:d("/docs/zen-of-sfmc/","112"),exact:!0,sidebar:"docs"}]}]}]},{path:"/sites/",component:d("/sites/","686"),routes:[{path:"/sites/",component:d("/sites/","db2"),routes:[{path:"/sites/tags/",component:d("/sites/tags/","44d"),exact:!0},{path:"/sites/tags/best-practice/",component:d("/sites/tags/best-practice/","162"),exact:!0},{path:"/sites/tags/faq/",component:d("/sites/tags/faq/","cb6"),exact:!0},{path:"/sites/tags/interaction-studio/",component:d("/sites/tags/interaction-studio/","1ea"),exact:!0},{path:"/sites/tags/marketing-cloud-personalization/",component:d("/sites/tags/marketing-cloud-personalization/","d3f"),exact:!0},{path:"/sites/tags/marketing-cloud/",component:d("/sites/tags/marketing-cloud/","24d"),exact:!0},{path:"/sites/tags/personalization/",component:d("/sites/tags/personalization/","505"),exact:!0},{path:"/sites/",component:d("/sites/","ddc"),routes:[{path:"/sites/category/faq/",component:d("/sites/category/faq/","fd6"),exact:!0,sidebar:"faq"},{path:"/sites/category/ideas/",component:d("/sites/category/ideas/","b7e"),exact:!0,sidebar:"ideas"},{path:"/sites/faq/how-to-get-sf-certification-vouchers/",component:d("/sites/faq/how-to-get-sf-certification-vouchers/","ef8"),exact:!0,sidebar:"faq"},{path:"/sites/faq/how-to-get-sfmc-hands-on-experience/",component:d("/sites/faq/how-to-get-sfmc-hands-on-experience/","c90"),exact:!0,sidebar:"faq"},{path:"/sites/ideas/marketing-cloud-ideas/",component:d("/sites/ideas/marketing-cloud-ideas/","bd0"),exact:!0,sidebar:"ideas"},{path:"/sites/ideas/mc-personalization-ideas/",component:d("/sites/ideas/mc-personalization-ideas/","90c"),exact:!0,sidebar:"ideas"},{path:"/sites/licence/",component:d("/sites/licence/","32f"),exact:!0},{path:"/sites/my-toolset/",component:d("/sites/my-toolset/","cc9"),exact:!0},{path:"/sites/newsletter/",component:d("/sites/newsletter/","16c"),exact:!0},{path:"/sites/privacy/",component:d("/sites/privacy/","c1f"),exact:!0}]}]}]},{path:"/",component:d("/","2e1"),exact:!0},{path:"*",component:d("*")}]},8848:(e,t,n)=>{"use strict";n.d(t,{o:()=>a,x:()=>s});var r=n(6540),o=n(4848);const a=r.createContext(!1);function s(e){let{children:t}=e;const[n,s]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{s(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},5022:(e,t,n)=>{"use strict";var r=n(6540),o=n(5338),a=n(545),s=n(4625),i=n(4784),c=n(1712);const l=[n(9128),n(5300),n(4753),n(5729),n(8252)];var u=n(2413),d=n(6347),f=n(2831),p=n(4848);function m(e){let{children:t}=e;return(0,p.jsx)(p.Fragment,{children:t})}var g=n(1141),h=n(7639),b=n(8180),y=n(6957),v=n(4239),w=n(2098),S=n(9503),x=n(1482),k=n(4609),E=n(1210);function _(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.A)(),r=(0,w.o)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,p.jsxs)(g.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,p.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,p.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,p.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function j(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.A)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.A)(),{pathname:r}=(0,d.zy)();return e+(0,k.Ks)((0,b.Ay)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,p.jsxs)(g.A,{children:[(0,p.jsx)("meta",{property:"og:url",content:o}),(0,p.jsx)("link",{rel:"canonical",href:o})]})}function O(){const{i18n:{currentLocale:e}}=(0,h.A)(),{metadata:t,image:n}=(0,y.p)();return(0,p.jsxs)(p.Fragment,{children:[(0,p.jsxs)(g.A,{children:[(0,p.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,p.jsx)("body",{className:S.w})]}),n&&(0,p.jsx)(v.be,{image:n}),(0,p.jsx)(j,{}),(0,p.jsx)(_,{}),(0,p.jsx)(E.A,{tag:x.C,locale:e}),(0,p.jsx)(g.A,{children:t.map(((e,t)=>(0,p.jsx)("meta",{...e},t)))})]})}const C=new Map;var T=n(8848),A=n(3366),P=n(6494);function I(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>o.forEach((e=>e?.()))}const N=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,P.A)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:s}=t;if(s){const e=decodeURIComponent(s.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),I("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function R(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,f.u)(u.A,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class L extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=c.A.canUseDOM?I("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=I("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),R(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,p.jsx)(N,{previousLocation:this.previousLocation,location:t,children:(0,p.jsx)(d.qh,{location:t,render:()=>e})})}}const D=L,M="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner",B="__docusaurus-base-url-issue-banner-suggestion-container";function z(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${M}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}((0,d.zy)());return(0,p.jsx)(D,{location:e,children:G})}function Y(){return(0,p.jsx)(H.A,{children:(0,p.jsx)(A.l,{children:(0,p.jsxs)(T.x,{children:[(0,p.jsxs)(m,{children:[(0,p.jsx)($,{}),(0,p.jsx)(O,{}),(0,p.jsx)(U,{}),(0,p.jsx)(K,{})]}),(0,p.jsx)(W,{})]})})})}var Q=n(4054);const Z=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var X=n(1604);const J=new Set,ee=new Set,te=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ne={prefetch:e=>{if(!(e=>!te()&&!ee.has(e)&&!J.has(e))(e))return!1;J.add(e);const t=(0,f.u)(u.A,e).flatMap((e=>{return t=e.route.path,Object.entries(Q).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,X.A)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Z(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!te()&&!ee.has(e))(e)&&(ee.add(e),R(e))},re=Object.freeze(ne);function oe(e){let{children:t}=e;return"hash"===i.default.future.experimental_router?(0,p.jsx)(s.I9,{children:t}):(0,p.jsx)(s.Kd,{children:t})}const ae=Boolean(!0);if(c.A.canUseDOM){window.docusaurus=re;const e=document.getElementById("__docusaurus"),t=(0,p.jsx)(a.vd,{children:(0,p.jsx)(oe,{children:(0,p.jsx)(Y,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(window.docusaurusRoot)window.docusaurusRoot.render(t);else if(ae)window.docusaurusRoot=o.hydrateRoot(e,t,{onRecoverableError:n});else{const r=o.createRoot(e,{onRecoverableError:n});r.render(t),window.docusaurusRoot=r}};R(window.location.pathname).then((()=>{(0,r.startTransition)(s)}))}},3366:(e,t,n)=>{"use strict";n.d(t,{o:()=>d,l:()=>f});var r=n(6540),o=n(4784);const a=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"docs-and-snippets","docs":[{"id":"ampscript/ampscript-style-guide","path":"/docs/ampscript/ampscript-style-guide","sidebar":"docs"},{"id":"config/sfmc-appexchange-solutions","path":"/docs/config/sfmc-appexchange-solutions","sidebar":"docs"},{"id":"config/sfmc-behavioral-triggers","path":"/docs/config/sfmc-behavioral-triggers","sidebar":"docs"},{"id":"config/sfmc-code-resource","path":"/docs/config/sfmc-code-resource","sidebar":"docs"},{"id":"config/sfmc-contact-deletion","path":"/docs/config/sfmc-contact-deletion","sidebar":"docs"},{"id":"config/sfmc-enhanced-send-log","path":"/docs/config/sfmc-enhanced-send-log","sidebar":"docs"},{"id":"config/sfmc-features-on-demand","path":"/docs/config/sfmc-features-on-demand","sidebar":"docs"},{"id":"config/sfmc-licence-limits","path":"/docs/config/sfmc-licence-limits","unlisted":true,"sidebar":"docs"},{"id":"config/sfmc-mcc-integration-patterns","path":"/docs/config/sfmc-mcc-integration-patterns","sidebar":"docs"},{"id":"config/sfmc-mobile-connect-data-views","path":"/docs/config/sfmc-mobile-connect-data-views","sidebar":"docs"},{"id":"config/sfmc-system-data-views","path":"/docs/config/sfmc-system-data-views","sidebar":"docs"},{"id":"docs-and-snippets","path":"/docs/","sidebar":"docs"},{"id":"interaction-studio/mcp-catalog-architecture","path":"/docs/interaction-studio/mcp-catalog-architecture","sidebar":"docs"},{"id":"interaction-studio/mcp-open-time-email","path":"/docs/interaction-studio/mcp-open-time-email","sidebar":"docs"},{"id":"interaction-studio/mcp-serverside-code-basics","path":"/docs/interaction-studio/mcp-serverside-code-basics","sidebar":"docs"},{"id":"interaction-studio/mcp-serverside-code-context","path":"/docs/interaction-studio/mcp-serverside-code-context","sidebar":"docs"},{"id":"interaction-studio/mcp-serverside-code-properties","path":"/docs/interaction-studio/mcp-serverside-code-properties","sidebar":"docs"},{"id":"interaction-studio/snippets/mcp-catalog-etl-metadata-viewer","path":"/docs/interaction-studio/snippets/mcp-catalog-etl-metadata-viewer","sidebar":"docs"},{"id":"js/js-dom","path":"/docs/js/js-dom","sidebar":"docs"},{"id":"js/js-if-and-switch","path":"/docs/js/js-if-and-switch","sidebar":"docs"},{"id":"js/js-loops","path":"/docs/js/js-loops","sidebar":"docs"},{"id":"js/snippets/engage-with-countdown","path":"/docs/js/snippets/engage-with-countdown","sidebar":"docs"},{"id":"js/snippets/export-import-document-sfmc-roles","path":"/docs/js/snippets/export-import-document-sfmc-roles","sidebar":"docs"},{"id":"js/snippets/tailor-with-data","path":"/docs/js/snippets/tailor-with-data","sidebar":"docs"},{"id":"sql/sfmc-sql-aggregate-functions","path":"/docs/sql/sfmc-sql-aggregate-functions","sidebar":"docs"},{"id":"sql/sfmc-sql-basics","path":"/docs/sql/sfmc-sql-basics","sidebar":"docs"},{"id":"sql/sfmc-sql-case","path":"/docs/sql/sfmc-sql-case","sidebar":"docs"},{"id":"sql/sfmc-sql-conversion-functions","path":"/docs/sql/sfmc-sql-conversion-functions","sidebar":"docs"},{"id":"sql/sfmc-sql-date-functions","path":"/docs/sql/sfmc-sql-date-functions","sidebar":"docs"},{"id":"sql/sfmc-sql-from","path":"/docs/sql/sfmc-sql-from","sidebar":"docs"},{"id":"sql/sfmc-sql-join","path":"/docs/sql/sfmc-sql-join","sidebar":"docs"},{"id":"sql/sfmc-sql-like","path":"/docs/sql/sfmc-sql-like","sidebar":"docs"},{"id":"sql/sfmc-sql-null-functions","path":"/docs/sql/sfmc-sql-null-functions","sidebar":"docs"},{"id":"sql/sfmc-sql-numeric-functions","path":"/docs/sql/sfmc-sql-numeric-functions","sidebar":"docs"},{"id":"sql/sfmc-sql-select","path":"/docs/sql/sfmc-sql-select","sidebar":"docs"},{"id":"sql/sfmc-sql-string-functions","path":"/docs/sql/sfmc-sql-string-functions","sidebar":"docs"},{"id":"sql/sfmc-sql-style-guide","path":"/docs/sql/sfmc-sql-style-guide","sidebar":"docs"},{"id":"sql/sfmc-sql-where","path":"/docs/sql/sfmc-sql-where","sidebar":"docs"},{"id":"sql/snippets/sfmc-sql-debugging-email-sends","path":"/docs/sql/snippets/sfmc-sql-debugging-email-sends","sidebar":"docs"},{"id":"sql/snippets/sfmc-sql-debugging-value-length","path":"/docs/sql/snippets/sfmc-sql-debugging-value-length","sidebar":"docs"},{"id":"ssjs/debugging-ssjs","path":"/docs/ssjs/debugging-ssjs","sidebar":"docs"},{"id":"ssjs/snippets/ampscript-in-ssjs","path":"/docs/ssjs/snippets/ampscript-in-ssjs","sidebar":"docs"},{"id":"ssjs/snippets/sfmc-cloud-page-apps","path":"/docs/ssjs/snippets/sfmc-cloud-page-apps","sidebar":"docs"},{"id":"ssjs/snippets/ssjs-mobileconnect-phone-change","path":"/docs/ssjs/snippets/ssjs-mobileconnect-phone-change","sidebar":"docs"},{"id":"ssjs/snippets/ssjs-script-template","path":"/docs/ssjs/snippets/ssjs-script-template","sidebar":"docs"},{"id":"ssjs/ssjs-if-and-switch","path":"/docs/ssjs/ssjs-if-and-switch","sidebar":"docs"},{"id":"ssjs/ssjs-loops","path":"/docs/ssjs/ssjs-loops","sidebar":"docs"},{"id":"ssjs/ssjs-style-guide","path":"/docs/ssjs/ssjs-style-guide","sidebar":"docs"},{"id":"ssjs/ssjs-vs-ampscript-performance","path":"/docs/ssjs/ssjs-vs-ampscript-performance","sidebar":"docs"},{"id":"webinars/sfmc-webinar-account-architecture","path":"/docs/webinars/sfmc-webinar-account-architecture","sidebar":"webinars"},{"id":"webinars/sfmc-webinar-architecting-web-solutions","path":"/docs/webinars/sfmc-webinar-architecting-web-solutions","sidebar":"webinars"},{"id":"webinars/sfmc-webinar-cloud-page-apps","path":"/docs/webinars/sfmc-webinar-cloud-page-apps","sidebar":"webinars"},{"id":"webinars/sfmc-webinar-salesforce-data-in-journey-builder","path":"/docs/webinars/sfmc-webinar-salesforce-data-in-journey-builder","sidebar":"webinars"},{"id":"zen-of-sfmc","path":"/docs/zen-of-sfmc","sidebar":"docs"},{"id":"/category/ssjs","path":"/docs/category/ssjs","sidebar":"docs"},{"id":"/category/-ssjs-snippets","path":"/docs/category/-ssjs-snippets","sidebar":"docs"},{"id":"/category/javascript","path":"/docs/category/javascript","sidebar":"docs"},{"id":"/category/-js-snippets","path":"/docs/category/-js-snippets","sidebar":"docs"},{"id":"/category/ampscript","path":"/docs/category/ampscript","sidebar":"docs"},{"id":"/category/-ampscript-snippets","path":"/docs/category/-ampscript-snippets","sidebar":"docs"},{"id":"/category/sfmc-sql","path":"/docs/category/sfmc-sql","sidebar":"docs"},{"id":"/category/-sql-snippets","path":"/docs/category/-sql-snippets","sidebar":"docs"},{"id":"/category/sfmc-config","path":"/docs/category/sfmc-config","sidebar":"docs"},{"id":"/category/mc-personalization","path":"/docs/category/mc-personalization","sidebar":"docs"},{"id":"/category/-serverside-code","path":"/docs/category/-serverside-code","sidebar":"docs"},{"id":"/category/-mc-personalization-snippets","path":"/docs/category/-mc-personalization-snippets","sidebar":"docs"},{"id":"/category/sfmc-webinars","path":"/docs/category/sfmc-webinars","sidebar":"webinars"}],"draftIds":["ssjs/ssjs-wsproxy"],"sidebars":{"docs":{"link":{"path":"/docs/zen-of-sfmc","label":"zen-of-sfmc"}},"webinars":{"link":{"path":"/docs/category/sfmc-webinars","label":"SFMC Webinars"}}}}],"breadcrumbs":true},"sites":{"path":"/sites","versions":[{"name":"current","label":"Next","isLast":true,"path":"/sites","mainDocId":"ideas/marketing-cloud-ideas","docs":[{"id":"faq/how-to-get-sf-certification-vouchers","path":"/sites/faq/how-to-get-sf-certification-vouchers","sidebar":"faq"},{"id":"faq/how-to-get-sfmc-hands-on-experience","path":"/sites/faq/how-to-get-sfmc-hands-on-experience","sidebar":"faq"},{"id":"ideas/marketing-cloud-ideas","path":"/sites/ideas/marketing-cloud-ideas","sidebar":"ideas"},{"id":"ideas/mc-personalization-ideas","path":"/sites/ideas/mc-personalization-ideas","sidebar":"ideas"},{"id":"licence","path":"/sites/licence"},{"id":"my-toolset","path":"/sites/my-toolset"},{"id":"newsletter","path":"/sites/newsletter"},{"id":"privacy","path":"/sites/privacy"},{"id":"/category/ideas","path":"/sites/category/ideas","sidebar":"ideas"},{"id":"/category/faq","path":"/sites/category/faq","sidebar":"faq"}],"draftIds":[],"sidebars":{"ideas":{"link":{"path":"/sites/category/ideas","label":"Ideas"}},"faq":{"link":{"path":"/sites/category/faq","label":"FAQ"}}}}],"breadcrumbs":true}},"docusaurus-plugin-google-gtag":{"default":{"trackingID":["GTM-N46LB5K"],"anonymizeIP":true,"id":"default"}}}'),s=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var i=n(2654);const c=JSON.parse('{"docusaurusVersion":"3.5.2","siteVersion":"1.5.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.5.2"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.5.2"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.5.2"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.5.2"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.5.2"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.5.2"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"3.5.2"},"docusaurus-plugin-ideal-image":{"type":"package","name":"@docusaurus/plugin-ideal-image","version":"3.5.2"},"docusaurus-plugin-client-redirects":{"type":"package","name":"@docusaurus/plugin-client-redirects","version":"3.5.2"},"docusaurus-theme-mermaid":{"type":"package","name":"@docusaurus/theme-mermaid","version":"3.5.2"}}}');var l=n(4848);const u={siteConfig:o.default,siteMetadata:c,globalData:a,i18n:s,codeTranslations:i},d=r.createContext(u);function f(e){let{children:t}=e;return(0,l.jsx)(d.Provider,{value:u,children:t})}},3832:(e,t,n)=>{"use strict";n.d(t,{A:()=>g});var r=n(6540),o=n(1712),a=n(1141),s=n(4609),i=n(7237),c=n(3363),l=n(4848);function u(e){let{error:t,tryAgain:n}=e;return(0,l.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,l.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,l.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,l.jsx)(d,{error:t})]})}function d(e){let{error:t}=e;const n=(0,s.rA)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,l.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function f(e){let{children:t}=e;return(0,l.jsx)(c.W,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function p(e){let{error:t,tryAgain:n}=e;return(0,l.jsx)(f,{children:(0,l.jsxs)(g,{fallback:()=>(0,l.jsx)(u,{error:t,tryAgain:n}),children:[(0,l.jsx)(a.A,{children:(0,l.jsx)("title",{children:"Page Error"})}),(0,l.jsx)(i.A,{children:(0,l.jsx)(u,{error:t,tryAgain:n})})]})})}const m=e=>(0,l.jsx)(p,{...e});class g extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.A.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??m)(e)}return e??null}}},1712:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},1141:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(545),o=n(4848);function a(e){return(0,o.jsx)(r.mg,{...e})}},4783:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});var r=n(6540),o=n(4625),a=n(4609),s=n(7639),i=n(877),c=n(1712),l=n(7344),u=n(8180),d=n(4848);function f(e,t){let{isNavLink:n,to:f,href:p,activeClassName:m,isActive:g,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...y}=e;const{siteConfig:v}=(0,s.A)(),{trailingSlash:w,baseUrl:S}=v,x=v.future.experimental_router,{withBaseUrl:k}=(0,u.hH)(),E=(0,l.A)(),_=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>_.current));const j=f||p;const O=(0,i.A)(j),C=j?.replace("pathname://","");let T=void 0!==C?(A=C,b&&(e=>e.startsWith("/"))(A)?k(A):A):void 0;var A;"hash"===x&&T?.startsWith("./")&&(T=T?.slice(1)),T&&O&&(T=(0,a.Ks)(T,{trailingSlash:w,baseUrl:S}));const P=(0,r.useRef)(!1),I=n?o.k2:o.N_,N=c.A.canUseIntersectionObserver,R=(0,r.useRef)(),L=()=>{P.current||null==T||(window.docusaurus.preload(T),P.current=!0)};(0,r.useEffect)((()=>(!N&&O&&c.A.canUseDOM&&null!=T&&window.docusaurus.prefetch(T),()=>{N&&R.current&&R.current.disconnect()})),[R,T,N,O]);const D=T?.startsWith("#")??!1,M=!y.target||"_self"===y.target,F=!T||!O||!M||D&&"hash"!==x;h||!D&&F||E.collectLink(T),y.id&&E.collectAnchor(y.id);const B={};return F?(0,d.jsx)("a",{ref:_,href:T,...j&&!O&&{target:"_blank",rel:"noopener noreferrer"},...y,...B}):(0,d.jsx)(I,{...y,onMouseEnter:L,onTouchStart:L,innerRef:e=>{_.current=e,N&&e&&O&&(R.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(R.current.unobserve(e),R.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),R.current.observe(e))},to:T,...n&&{isActive:g,activeClassName:m},...B})}const p=r.forwardRef(f)},3230:(e,t,n)=>{"use strict";n.d(t,{A:()=>l,T:()=>c});var r=n(6540),o=n(4848);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var s=n(2654);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return s[t??n]??n??t}function c(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const s=i({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(s,r)})}},4598:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r="default"},877:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{A:()=>o,z:()=>r})},8180:(e,t,n)=>{"use strict";n.d(t,{Ay:()=>i,hH:()=>s});var r=n(6540),o=n(7639),a=n(877);function s(){const{siteConfig:e}=(0,o.A)(),{baseUrl:t,url:n}=e,s=e.future.experimental_router,i=(0,r.useCallback)(((e,r)=>function(e){let{siteUrl:t,baseUrl:n,url:r,options:{forcePrependBaseUrl:o=!1,absolute:s=!1}={},router:i}=e;if(!r||r.startsWith("#")||(0,a.z)(r))return r;if("hash"===i)return r.startsWith("/")?`.${r}`:`./${r}`;if(o)return n+r.replace(/^\//,"");if(r===n.replace(/\/$/,""))return n;const c=r.startsWith(n)?r:n+r.replace(/^\//,"");return s?t+c:c}({siteUrl:n,baseUrl:t,url:e,options:r,router:s})),[n,t,s]);return{withBaseUrl:i}}function i(e,t){void 0===t&&(t={});const{withBaseUrl:n}=s();return n(e,t)}},7344:(e,t,n)=>{"use strict";n.d(t,{A:()=>s});var r=n(6540);n(4848);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function s(){return a()}},7639:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(3366);function a(){return(0,r.useContext)(o.o)}},1062:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(6540),o=n(8848);function a(){return(0,r.useContext)(o.o)}},6494:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});var r=n(6540);const o=n(1712).A.canUseDOM?r.useLayoutEffect:r.useEffect},1604:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,s]=n;const i=o?`${o}.${a}`:a;r(s)?e(s,i):t[i]=s}))}(e),t}},3363:(e,t,n)=>{"use strict";n.d(t,{W:()=>s,o:()=>a});var r=n(6540),o=n(4848);const a=r.createContext(null);function s(e){let{children:t,value:n}=e;const s=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:s,value:n})),[s,n]);return(0,o.jsx)(a.Provider,{value:i,children:t})}},6457:(e,t,n)=>{"use strict";n.d(t,{VQ:()=>h,XK:()=>v,g1:()=>y});var r=n(6540),o=n(4721),a=n(4598),s=n(6957),i=n(9900),c=n(4799),l=n(4848);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,i.Wf)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,i.Wf)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,i.Wf)(u(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const p=r.createContext(null);function m(){const e=(0,o.Gy)(),t=(0,s.p)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,i]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{i(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=d.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),i((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return(0,l.jsx)(p.Provider,{value:n,children:t})}function h(e){let{children:t}=e;return(0,l.jsx)(g,{children:t})}function b(){const e=(0,r.useContext)(p);if(!e)throw new c.dV("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=a.W);const t=(0,o.ht)(e),[n,s]=b(),{preferredVersionName:i}=n[e];return{preferredVersion:t.versions.find((e=>e.name===i))??null,savePreferredVersionName:(0,r.useCallback)((t=>{s.savePreferredVersion(e,t)}),[s,e])}}function v(){const e=(0,o.Gy)(),[t]=b();function n(n){const r=e[n],{preferredVersionName:o}=t[n];return r.versions.find((e=>e.name===o))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},3718:(e,t,n)=>{"use strict";n.d(t,{k:()=>a,v:()=>s});var r=n(4721),o=n(6457);function a(e,t){return`docs-${e}-${t}`}function s(){const e=(0,r.Gy)(),t=(0,r.gk)(),n=(0,o.XK)();return[...Object.keys(e).map((function(r){const o=t?.activePlugin.pluginId===r?t.activeVersion:void 0,s=n[r],i=e[r].versions.find((e=>e.isLast));return a(r,(o??s??i).name)}))]}},40:(e,t,n)=>{"use strict";n.d(t,{V:()=>c,t:()=>l});var r=n(6540),o=n(4799),a=n(4848);const s=Symbol("EmptyContext"),i=r.createContext(s);function c(e){let{children:t,name:n,items:o}=e;const s=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(i.Provider,{value:s,children:t})}function l(){const e=(0,r.useContext)(i);if(e===s)throw new o.dV("DocsSidebarProvider");return e}},5357:(e,t,n)=>{"use strict";n.d(t,{$S:()=>m,B5:()=>_,Nr:()=>p,OF:()=>S,QB:()=>E,Vd:()=>x,Y:()=>v,cC:()=>f,d1:()=>j,fW:()=>k,w8:()=>b});var r=n(6540),o=n(6347),a=n(2831),s=n(4721),i=n(260),c=n(5167),l=n(6457),u=n(1704),d=n(40);function f(e){const t=(0,u.r)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function p(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=p(t);if(e)return e}}(e):void 0:e.href}function m(){const{pathname:e}=(0,o.zy)(),t=(0,d.t)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=w({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const g=(e,t)=>void 0!==e&&(0,i.ys)(e,t),h=(e,t)=>e.some((e=>b(e,t)));function b(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||h(e.items,t))}function y(e,t){switch(e.type){case"category":return b(e,t)||e.items.some((e=>y(e,t)));case"link":return!e.unlisted||b(e,t);default:return!0}}function v(e,t){return(0,r.useMemo)((()=>e.filter((e=>y(e,t)))),[e,t])}function w(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,i.ys)(a.href,n)||e(a.items))||"link"===a.type&&(0,i.ys)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function S(){const e=(0,d.t)(),{pathname:t}=(0,o.zy)(),n=(0,s.vT)()?.pluginData.breadcrumbs;return!1!==n&&e?w({sidebarItems:e.items,pathname:t}):null}function x(e){const{activeVersion:t}=(0,s.zK)(e),{preferredVersion:n}=(0,l.g1)(e),o=(0,s.r7)(e);return(0,r.useMemo)((()=>(0,c.sb)([t,n,o].filter(Boolean))),[t,n,o])}function k(e,t){const n=x(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function E(e,t){const n=x(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,c.sb)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function _(e){let{route:t}=e;const n=(0,o.zy)(),r=(0,u.r)(),s=t.routes,i=s.find((e=>(0,o.B6)(n.pathname,e)));if(!i)return null;const c=i.sidebar,l=c?r.docsSidebars[c]:void 0;return{docElement:(0,a.v)(s),sidebarName:c,sidebarItems:l}}function j(e){return e.filter((e=>!("category"===e.type||"link"===e.type)||!!p(e)))}},1704:(e,t,n)=>{"use strict";n.d(t,{n:()=>i,r:()=>c});var r=n(6540),o=n(4799),a=n(4848);const s=r.createContext(null);function i(e){let{children:t,version:n}=e;return(0,a.jsx)(s.Provider,{value:n,children:t})}function c(){const e=(0,r.useContext)(s);if(null===e)throw new o.dV("DocsVersionProvider");return e}},4721:(e,t,n)=>{"use strict";n.d(t,{zK:()=>b,vT:()=>p,gk:()=>m,Gy:()=>d,HW:()=>y,ht:()=>f,r7:()=>h,jh:()=>g});var r=n(6347),o=n(7639),a=n(4598);function s(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.A)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const i=e=>e.versions.find((e=>e.isLast));function c(e,t){return[...e.versions].sort(((e,t)=>e.path===t.path?0:e.path.includes(t.path)?-1:t.path.includes(e.path)?1:0)).find((e=>!!(0,r.B6)(t,{path:e.path,exact:!1,strict:!1})))}function l(e,t){const n=c(e,t),o=n?.docs.find((e=>!!(0,r.B6)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const u={},d=()=>s("docusaurus-plugin-content-docs")??u,f=e=>{try{return function(e,t,n){void 0===t&&(t=a.W),void 0===n&&(n={});const r=s(e),o=r?.[t];if(!o&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return o}("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw new Error("You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled"+("Default"===e?"":` (pluginId=${e}`),{cause:t})}};function p(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.zy)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.B6)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return a}(t,n,e)}function m(e){void 0===e&&(e={});const t=p(e),{pathname:n}=(0,r.zy)();if(!t)return;return{activePlugin:t,activeVersion:c(t.pluginData,n)}}function g(e){return f(e).versions}function h(e){const t=f(e);return i(t)}function b(e){const t=f(e),{pathname:n}=(0,r.zy)();return l(t,n)}function y(e){const t=f(e),{pathname:n}=(0,r.zy)();return function(e,t){const n=i(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},9128:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},5729:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(5947),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},4753:(e,t,n)=>{"use strict";var r=n(1765),o=n(4784);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(9700),n(1255)(`./prism-${e}`)})),delete globalThis.Prism}(r.My)},5225:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(4164),o=n(3230),a=n(6957),s=n(4783),i=n(7344);const c={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var l=n(4848);function u(e){let{as:t,id:n,...u}=e;const d=(0,i.A)(),{navbar:{hideOnScroll:f}}=(0,a.p)();if("h1"===t||!n)return(0,l.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const p=(0,o.T)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,l.jsxs)(t,{...u,className:(0,r.A)("anchor",f?c.anchorWithHideOnScrollNavbar:c.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,l.jsx)(s.A,{className:"hash-link",to:`#${n}`,"aria-label":p,title:p,children:"\u200b"})]})}},716:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(4848);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},7237:(e,t,n)=>{"use strict";n.d(t,{A:()=>xt});var r=n(6540),o=n(4164),a=n(3832),s=n(4239),i=n(6347),c=n(3230),l=n(4067),u=n(4848);const d="__docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,r.useRef)(null),{action:t}=(0,i.W6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,l.$)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,c.T)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function g(e){const t=e.children??m,{containerRef:n,onClick:r}=p();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var h=n(8630),b=n(9503);const y={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(g,{className:y.skipToContent})}var w=n(6957),S=n(2);function x(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...s}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...s,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const k={closeButton:"closeButton_CVFx"};function E(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,c.T)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.A)("clean-btn close",k.closeButton,e.className),children:(0,u.jsx)(x,{width:14,height:14,strokeWidth:3.1})})}const _={content:"content_knG7"};function j(e){const{announcementBar:t}=(0,w.p)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.A)(_.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const O={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function C(){const{announcementBar:e}=(0,w.p)(),{isActive:t,close:n}=(0,S.M)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:O.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:O.announcementBarPlaceholder}),(0,u.jsx)(j,{className:O.announcementBarContent}),a&&(0,u.jsx)(E,{onClick:n,className:O.announcementBarClose})]})}var T=n(1938),A=n(4245);var P=n(4799),I=n(763);const N=r.createContext(null);function R(e){let{children:t}=e;const n=function(){const e=(0,T.M)(),t=(0,I.YL)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,s=(0,P.ZC)(a);return(0,r.useEffect)((()=>{a&&!s&&o(!0)}),[a,s]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(N.Provider,{value:n,children:t})}function L(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function D(){const e=(0,r.useContext)(N);if(!e)throw new P.dV("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,I.YL)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:L(a)})),[o,a,t])}function M(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=D();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.A)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var F=n(7710),B=n(1062);function z(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function q(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function $(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const s=(0,B.A)(),i=(0,c.T)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,c.T)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.T)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.A)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.A)("clean-btn",U.toggleButton,!s&&U.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!s,title:i,"aria-label":i,"aria-live":"polite",children:[(0,u.jsx)(z,{className:(0,o.A)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)(q,{className:(0,o.A)(U.toggleIcon,U.darkToggleIcon)})]})})}const H=r.memo($),V={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function W(e){let{className:t}=e;const n=(0,w.p)().navbar.style,r=(0,w.p)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,F.G)();return r?null:(0,u.jsx)(H,{className:t,buttonClassName:"dark"===n?V.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var G=n(20);function K(){return(0,u.jsx)(G.A,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Y(){const e=(0,T.M)();return(0,u.jsx)("button",{type:"button","aria-label":(0,c.T)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(x,{color:"var(--ifm-color-emphasis-600)"})})}function Q(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(K,{}),(0,u.jsx)(W,{className:"margin-right--md"}),(0,u.jsx)(Y,{})]})}var Z=n(4783),X=n(8180),J=n(877),ee=n(7865),te=n(716);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:s,isDropdownLink:i,prependBaseUrlToHref:c,...l}=e;const d=(0,X.Ay)(r),f=(0,X.Ay)(t),p=(0,X.Ay)(o,{forcePrependBaseUrl:!0}),m=a&&o&&!(0,J.A)(o),g=s?{dangerouslySetInnerHTML:{__html:s}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,m&&(0,u.jsx)(te.A,{...i&&{width:12,height:12}})]})};return o?(0,u.jsx)(Z.A,{href:c?p:o,...l,...g}):(0,u.jsx)(Z.A,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?(0,ee.G)(n,t.pathname):t.pathname.startsWith(f)},...l,...g})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.A)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.A)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var se=n(4549),ie=n(260),ce=n(7639);const le={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,ie.ys)(e.to,t)||!!(0,ee.G)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:s,...i}=e;const c=(0,r.useRef)(null),[l,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[c]),(0,u.jsxs)("div",{ref:c,className:(0,o.A)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":l}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":l,role:"button",href:i.to?void 0:"#",className:(0,o.A)("navbar__link",a),...i,onClick:i.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!l))},children:i.children??i.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(Fe,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function fe(e){let{items:t,className:n,position:a,onClick:s,...c}=e;const l=function(){const{siteConfig:{baseUrl:e}}=(0,ce.A)(),{pathname:t}=(0,i.zy)();return t.replace(e,"/")}(),d=ue(t,l),{collapsed:f,toggleCollapsed:p,setCollapsed:m}=(0,se.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[l,d,m]),(0,u.jsxs)("li",{className:(0,o.A)("menu__list-item",{"menu__list-item--collapsed":f}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.A)(le.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...c,onClick:e=>{e.preventDefault(),p()},children:c.children??c.label}),(0,u.jsx)(se.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:f,children:t.map(((e,t)=>(0,r.createElement)(Fe,{mobile:!0,isDropdownItem:!0,onClick:s,activeClassName:"menu__link--active",...e,key:t})))})]})}function pe(e){let{mobile:t=!1,...n}=e;const r=t?fe:de;return(0,u.jsx)(r,{...n})}var me=n(2098);function ge(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const he="iconLanguage_nlXk";var be=n(961),ye=n(5600),ve=n(1141),we=n(1142),Se=n(2177),xe=n(1482),ke=n(3718);function Ee(){return[`language:${(0,ce.A)().i18n.currentLocale}`,function(){const e=(0,ke.v)();return[xe.C,...e]}().map((e=>`docusaurus_tag:${e}`))]}const _e={button:{buttonText:(0,c.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.T)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.T)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.T)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.T)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.T)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.T)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.T)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.T)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.T)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.T)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.T)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.T)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.T)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.T)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.T)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.T)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.T)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.T)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.T)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.T)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let je=null;function Oe(e){let{hit:t,children:n}=e;return(0,u.jsx)(Z.A,{to:t.url,children:n})}function Ce(e){let{state:t,onClose:n}=e;const r=(0,we.w)();return(0,u.jsx)(Z.A,{to:r(t.query),onClick:n,children:(0,u.jsx)(c.A,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits},children:"See all {count} results"})})}function Te(e){let{contextualSearch:t,externalUrlRegex:o,...a}=e;const{siteMetadata:s}=(0,ce.A)(),c=(0,Se.C)(),l=Ee(),d=a.searchParameters?.facetFilters??[],f=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(l,d):d,p={...a.searchParameters,facetFilters:f},m=(0,i.W6)(),g=(0,r.useRef)(null),h=(0,r.useRef)(null),[b,y]=(0,r.useState)(!1),[v,w]=(0,r.useState)(void 0),S=(0,r.useCallback)((()=>je?Promise.resolve():Promise.all([n.e(8158).then(n.bind(n,8158)),Promise.all([n.e(1869),n.e(8913)]).then(n.bind(n,8913)),Promise.all([n.e(1869),n.e(2516)]).then(n.bind(n,135))]).then((e=>{let[{DocSearchModal:t}]=e;je=t}))),[]),x=(0,r.useCallback)((()=>{if(!g.current){const e=document.createElement("div");g.current=e,document.body.insertBefore(e,document.body.firstChild)}}),[]),k=(0,r.useCallback)((()=>{x(),S().then((()=>y(!0)))}),[S,x]),E=(0,r.useCallback)((()=>{y(!1),h.current?.focus()}),[]),_=(0,r.useCallback)((e=>{"f"===e.key&&(e.metaKey||e.ctrlKey)||(e.preventDefault(),w(e.key),k())}),[k]),j=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee.G)(o,t)?window.location.href=t:m.push(t)}}).current,O=(0,r.useRef)((e=>a.transformItems?a.transformItems(e):e.map((e=>({...e,url:c(e.url)}))))).current,C=(0,r.useMemo)((()=>e=>(0,u.jsx)(Ce,{...e,onClose:E})),[E]),T=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",s.docusaurusVersion),e)),[s.docusaurusVersion]);return(0,ye.E8)({isOpen:b,onOpen:k,onClose:E,onInput:_,searchButtonRef:h}),(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ve.A,{children:(0,u.jsx)("link",{rel:"preconnect",href:`https://${a.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})}),(0,u.jsx)(ye.Bc,{onTouchStart:S,onFocus:S,onMouseOver:S,onClick:k,ref:h,translations:_e.button}),b&&je&&g.current&&(0,be.createPortal)((0,u.jsx)(je,{onClose:E,initialScrollY:window.scrollY,initialQuery:v,navigator:j,transformItems:O,hitComponent:Oe,transformSearchClient:T,...a.searchPagePath&&{resultsFooterComponent:C},...a,searchParameters:p,placeholder:_e.placeholder,translations:_e.modal}),g.current)]})}function Ae(){const{siteConfig:e}=(0,ce.A)();return(0,u.jsx)(Te,{...e.themeConfig.algolia})}const Pe={navbarSearchContainer:"navbarSearchContainer_Bca1"};function Ie(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.A)(n,Pe.navbarSearchContainer),children:t})}var Ne=n(4721),Re=n(5357);var Le=n(6457);function De(e,t){return t.alternateDocVersions[e.name]??function(e){return e.docs.find((t=>t.id===e.mainDocId))}(e)}const Me={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:s,locales:l,localeConfigs:d}}=(0,ce.A)(),f=(0,me.o)(),{search:p,hash:m}=(0,i.zy)(),g=[...n,...l.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${m}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===s?t?"menu__link--active":"dropdown__link--active":""}})),...r],h=t?(0,c.T)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[s].label;return(0,u.jsx)(pe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(ge,{className:he}),h]}),items:g})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Ie,{className:n,children:(0,u.jsx)(Ae,{})})},dropdown:pe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const s=a?"li":"div";return(0,u.jsx)(s,{className:(0,o.A)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ne.zK)(r),s=(0,Re.QB)(t,r),i=a?.path===s?.path;return null===s||s.unlisted&&!i?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>i||!!a?.sidebar&&a.sidebar===s.sidebar,label:n??s.id,to:s.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ne.zK)(r),s=(0,Re.fW)(t,r).link;if(!s)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??s.label,to:s.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,Re.Vd)(r)[0],s=t??a.label,i=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:s,to:i})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...s}=e;const{search:l,hash:d}=(0,i.zy)(),f=(0,Ne.zK)(n),p=(0,Ne.jh)(n),{savePreferredVersionName:m}=(0,Le.g1)(n),g=[...o,...p.map((function(e){const t=De(e,f);return{label:e.label,to:`${t.path}${l}${d}`,isActive:()=>e===f.activeVersion,onClick:()=>m(e.name)}})),...a],h=(0,Re.Vd)(n)[0],b=t&&g.length>1?(0,c.T)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):h.label,y=t&&g.length>1?void 0:De(h,f).path;return g.length<=1?(0,u.jsx)(ae,{...s,mobile:t,label:b,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(pe,{...s,mobile:t,label:b,to:y,items:g,isActive:r?()=>!1:void 0})}};function Fe(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Me[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function Be(){const e=(0,T.M)(),t=(0,w.p)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(Fe,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function ze(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(c.A,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function qe(){const e=0===(0,w.p)().navbar.items.length,t=D();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(ze,{onClick:()=>t.hide()}),t.content]})}function Ue(){const e=(0,T.M)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(M,{header:(0,u.jsx)(Q,{}),primaryMenu:(0,u.jsx)(Be,{}),secondaryMenu:(0,u.jsx)(qe,{})}):null}const $e={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function He(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.A)("navbar-sidebar__backdrop",e.className)})}function Ve(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,w.p)(),s=(0,T.M)(),{navbarRef:i,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),s=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,A.Mq)(((t,r)=>{let{scrollY:s}=t;if(!e)return;if(s=i?n(!1):s+l{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:s,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:i,"aria-label":(0,c.T)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.A)("navbar","navbar--fixed-top",n&&[$e.navbarHideable,!d&&$e.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":s.shown}),children:[t,(0,u.jsx)(He,{onClick:s.toggle}),(0,u.jsx)(Ue,{})]})}var We=n(4176);const Ge="right";function Ke(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function Ye(){const{toggle:e,shown:t}=(0,T.M)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,c.T)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(Ke,{})})}const Qe={colorModeToggle:"colorModeToggle_DEke"};function Ze(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(We.k2,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(Fe,{...e})},t)))})}function Xe(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function Je(){const e=(0,T.M)(),t=(0,w.p)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??Ge)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(Xe,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(Ye,{}),(0,u.jsx)(K,{}),(0,u.jsx)(Ze,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Ze,{items:r}),(0,u.jsx)(W,{className:Qe.colorModeToggle}),!o&&(0,u.jsx)(Ie,{children:(0,u.jsx)(Ae,{})})]})})}function et(){return(0,u.jsx)(Ve,{children:(0,u.jsx)(Je,{})})}function tt(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...s}=t,i=(0,X.Ay)(n),c=(0,X.Ay)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Z.A,{className:"footer__link-item",...r?{href:a?c:r}:{to:i},...s,children:[o,r&&!(0,J.A)(r)&&(0,u.jsx)(te.A,{})]})}function nt(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(tt,{item:t})},t.href??t.to)}function rt(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(nt,{item:e},t)))})]})}function ot(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(rt,{column:e},t)))})}function at(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function st(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(tt,{item:t})}function it(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(st,{item:e}),t.length!==n+1&&(0,u.jsx)(at,{})]},n)))})})}function ct(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(ot,{columns:t}):(0,u.jsx)(it,{links:t})}var lt=n(975);const ut={footerLogoLink:"footerLogoLink_BH7S"};function dt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.hH)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(lt.A,{className:(0,o.A)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function ft(e){let{logo:t}=e;return t.href?(0,u.jsx)(Z.A,{href:t.href,className:ut.footerLogoLink,target:t.target,children:(0,u.jsx)(dt,{logo:t})}):(0,u.jsx)(dt,{logo:t})}function pt(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function mt(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.A)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function gt(){const{footer:e}=(0,w.p)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(mt,{style:o,links:n&&n.length>0&&(0,u.jsx)(ct,{links:n}),logo:r&&(0,u.jsx)(ft,{logo:r}),copyright:t&&(0,u.jsx)(pt,{copyright:t})})}const ht=r.memo(gt),bt=(0,P.fM)([F.a,S.o,A.Tv,Le.VQ,s.Jx,function(e){let{children:t}=e;return(0,u.jsx)(I.y_,{children:(0,u.jsx)(T.e,{children:(0,u.jsx)(R,{children:t})})})}]);function yt(e){let{children:t}=e;return(0,u.jsx)(bt,{children:t})}var vt=n(5225);function wt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(vt.A,{as:"h1",className:"hero__title",children:(0,u.jsx)(c.A,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(We.a2,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(We.bq,{error:t})})]})})})}const St={mainWrapper:"mainWrapper_z2l0"};function xt(e){const{children:t,noFooter:n,wrapperClassName:r,title:i,description:c}=e;return(0,b.J)(),(0,u.jsxs)(yt,{children:[(0,u.jsx)(s.be,{title:i,description:c}),(0,u.jsx)(v,{}),(0,u.jsx)(C,{}),(0,u.jsx)(et,{}),(0,u.jsx)("div",{id:d,className:(0,o.A)(h.G.wrapper.main,St.mainWrapper,r),children:(0,u.jsx)(a.A,{fallback:e=>(0,u.jsx)(wt,{...e}),children:t})}),!n&&(0,u.jsx)(ht,{})]})}},20:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(6540);var r=n(4783),o=n(8180),a=n(7639),s=n(6957),i=n(975),c=n(4848);function l(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.Ay)(t.src),dark:(0,o.Ay)(t.srcDark||t.src)},s=(0,c.jsx)(i.A,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,c.jsx)("div",{className:r,children:s}):s}function u(e){const{siteConfig:{title:t}}=(0,a.A)(),{navbar:{title:n,logo:i}}=(0,s.p)(),{imageClassName:u,titleClassName:d,...f}=e,p=(0,o.Ay)(i?.href||"/"),m=n?"":t,g=i?.alt??m;return(0,c.jsxs)(r.A,{to:p,...f,...i?.target&&{target:i.target},children:[i&&(0,c.jsx)(l,{logo:i,alt:g,imageClassName:u}),null!=n&&(0,c.jsx)("b",{className:d,children:n})]})}},1210:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(6540);var r=n(1141),o=n(4848);function a(e){let{locale:t,version:n,tag:a}=e;const s=t;return(0,o.jsxs)(r.A,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),s&&(0,o.jsx)("meta",{name:"docsearch:language",content:s}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},975:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});var r=n(6540),o=n(4164),a=n(1062),s=n(7710);const i={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var c=n(4848);function l(e){let{className:t,children:n}=e;const l=(0,a.A)(),{colorMode:u}=(0,s.G)();return(0,c.jsx)(c.Fragment,{children:(l?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.A)(t,i.themedComponent,i[`themedComponent--${e}`])});return(0,c.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,c.jsx)(l,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,c.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},4549:(e,t,n)=>{"use strict";n.d(t,{N:()=>b,u:()=>l});var r=n(6540),o=n(1712),a=n(6494),s=n(6350),i=n(4848);const c="ease-in-out";function l(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function f(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function p(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,s.O)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??c}`,height:`${t}px`}}function i(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return f(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(i(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{i()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function m(e){if(!o.A.canUseDOM)return e?u:d}function g(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:s,className:c,disableSSRStyle:l}=e;const u=(0,r.useRef)(null);return p({collapsibleRef:u,collapsed:n,animation:a}),(0,i.jsx)(t,{ref:u,style:l?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(f(u.current,n),s?.(n))},className:c,children:o})}function h(e){let{collapsed:t,...n}=e;const[o,s]=(0,r.useState)(!t),[c,l]=(0,r.useState)(t);return(0,a.A)((()=>{t||s(!0)}),[t]),(0,a.A)((()=>{o&&l(t)}),[o,t]),o?(0,i.jsx)(g,{...n,collapsed:c}):null}function b(e){let{lazy:t,...n}=e;const r=t?h:g;return(0,i.jsx)(r,{...n})}},2:(e,t,n)=>{"use strict";n.d(t,{M:()=>g,o:()=>m});var r=n(6540),o=n(1062),a=n(9900),s=n(4799),i=n(6957),c=n(4848);const l=(0,a.Wf)("docusaurus.announcement.dismiss"),u=(0,a.Wf)("docusaurus.announcement.id"),d=()=>"true"===l.get(),f=e=>l.set(String(e)),p=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,i.p)(),t=(0,o.A)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const s=(0,r.useCallback)((()=>{f(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&f(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:s})),[e,n,s])}();return(0,c.jsx)(p.Provider,{value:n,children:t})}function g(){const e=(0,r.useContext)(p);if(!e)throw new s.dV("AnnouncementBarProvider");return e}},7710:(e,t,n)=>{"use strict";n.d(t,{G:()=>b,a:()=>h});var r=n(6540),o=n(1712),a=n(4799),s=n(9900),i=n(6957),c=n(4848);const l=r.createContext(void 0),u="theme",d=(0,s.Wf)(u),f={light:"light",dark:"dark"},p=e=>e===f.dark?f.dark:f.light,m=e=>o.A.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e),g=e=>{d.set(p(e))};function h(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,i.p)(),[o,a]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const s=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&g(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?f.dark:f.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",p(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&s(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,s]);const c=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||c.current?c.current=window.matchMedia("print").matches:s(null)};return e.addListener(r),()=>e.removeListener(r)}),[s,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:s,get isDarkTheme(){return o===f.dark},setLightTheme(){s(f.light)},setDarkTheme(){s(f.dark)}})),[o,s])}();return(0,c.jsx)(l.Provider,{value:n,children:t})}function b(){const e=(0,r.useContext)(l);if(null==e)throw new a.dV("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},1938:(e,t,n)=>{"use strict";n.d(t,{M:()=>p,e:()=>f});var r=n(6540),o=n(763),a=n(2216),s=n(2814),i=n(6957),c=n(4799),l=n(4848);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.YL)(),{items:t}=(0,i.p)().navbar;return 0===t.length&&!e.component}(),t=(0,a.l)(),n=!e&&"mobile"===t,[c,l]=(0,r.useState)(!1);(0,s.$Z)((()=>{if(c)return l(!1),!1}));const u=(0,r.useCallback)((()=>{l((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&l(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:c})),[e,n,u,c])}function f(e){let{children:t}=e;const n=d();return(0,l.jsx)(u.Provider,{value:n,children:t})}function p(){const e=r.useContext(u);if(void 0===e)throw new c.dV("NavbarMobileSidebarProvider");return e}},763:(e,t,n)=>{"use strict";n.d(t,{GX:()=>l,YL:()=>c,y_:()=>i});var r=n(6540),o=n(4799),a=n(4848);const s=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(s.Provider,{value:n,children:t})}function c(){const e=(0,r.useContext)(s);if(!e)throw new o.dV("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const a=(0,r.useContext)(s);if(!a)throw new o.dV("NavbarSecondaryMenuContentProvider");const[,i]=a,c=(0,o.Be)(n);return(0,r.useEffect)((()=>{i({component:t,props:c})}),[i,t,c]),(0,r.useEffect)((()=>()=>i({component:null,props:null})),[i]),null}},9503:(e,t,n)=>{"use strict";n.d(t,{w:()=>o,J:()=>a});var r=n(6540);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},1142:(e,t,n)=>{"use strict";n.d(t,{b:()=>i,w:()=>c});var r=n(6540),o=n(7639),a=n(2814);const s="q";function i(){return(0,a.l)(s)}function c(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,o.A)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>`${e}${n}?${s}=${encodeURIComponent(t)}`),[e,n])}},2216:(e,t,n)=>{"use strict";n.d(t,{l:()=>i});var r=n(6540),o=n(1712);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},s=996;function i(e){let{desktopBreakpoint:t=s}=void 0===e?{}:e;const[n,i]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){i(function(e){if(!o.A.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},8630:(e,t,n)=>{"use strict";n.d(t,{G:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",blogAuthorsListPage:"blog-authors-list-page",blogAuthorsPostsPage:"blog-authors-posts-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",draftBanner:"theme-draft-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},6350:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{O:()=>r})},4176:(e,t,n)=>{"use strict";n.d(t,{bq:()=>u,MN:()=>l,a2:()=>c,k2:()=>d});var r=n(6540),o=n(3230),a=n(4609);const s={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};var i=n(4848);function c(e){return(0,i.jsx)("button",{type:"button",...e,children:(0,i.jsx)(o.A,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function l(e){let{error:t,tryAgain:n}=e;return(0,i.jsxs)("div",{className:s.errorBoundaryFallback,children:[(0,i.jsx)("p",{children:t.message}),(0,i.jsx)(c,{onClick:n})]})}function u(e){let{error:t}=e;const n=(0,a.rA)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,i.jsx)("p",{className:s.errorBoundaryError,children:n})}class d extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}},7942:(e,t,n)=>{"use strict";n.d(t,{s:()=>o});var r=n(7639);function o(e){const{siteConfig:t}=(0,r.A)(),{title:n,titleDelimiter:o}=t;return e?.trim().length?`${e.trim()} ${o} ${n}`:n}},2814:(e,t,n)=>{"use strict";n.d(t,{$Z:()=>s,aZ:()=>c,l:()=>l});var r=n(6540),o=n(6347),a=n(4799);function s(e){!function(e){const t=(0,o.W6)(),n=(0,a._q)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function i(e){const t=(0,o.W6)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}function c(e){return i((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function l(e){const t=c(e)??"",n=function(e){const t=(0,o.W6)();return(0,r.useCallback)(((n,r)=>{const o=new URLSearchParams(t.location.search);n?o.set(e,n):o.delete(e),(r?.push?t.push:t.replace)({search:o.toString()})}),[e,t])}(e);return[t,n]}},5167:(e,t,n)=>{"use strict";function r(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,r)=>e.findIndex((e=>t(e,n)))!==r))}function o(e){return Array.from(new Set(e))}n.d(t,{XI:()=>r,sb:()=>o})},4239:(e,t,n)=>{"use strict";n.d(t,{e3:()=>p,be:()=>d,Jx:()=>m});var r=n(6540),o=n(4164),a=n(1141),s=n(3363);function i(){const e=r.useContext(s.o);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var c=n(8180),l=n(7942),u=n(4848);function d(e){let{title:t,description:n,keywords:r,image:o,children:s}=e;const i=(0,l.s)(t),{withBaseUrl:d}=(0,c.hH)(),f=o?d(o,{absolute:!0}):void 0;return(0,u.jsxs)(a.A,{children:[t&&(0,u.jsx)("title",{children:i}),t&&(0,u.jsx)("meta",{property:"og:title",content:i}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),f&&(0,u.jsx)("meta",{property:"og:image",content:f}),f&&(0,u.jsx)("meta",{name:"twitter:image",content:f}),s]})}const f=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const s=r.useContext(f),i=(0,o.A)(s,t);return(0,u.jsxs)(f.Provider,{value:i,children:[(0,u.jsx)(a.A,{children:(0,u.jsx)("html",{className:i})}),n]})}function m(e){let{children:t}=e;const n=i(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(p,{className:(0,o.A)(r,a),children:t})}},4799:(e,t,n)=>{"use strict";n.d(t,{Be:()=>l,ZC:()=>i,_q:()=>s,dV:()=>c,fM:()=>u});var r=n(6540),o=n(6494),a=n(4848);function s(e){const t=(0,r.useRef)(e);return(0,o.A)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return(0,o.A)((()=>{t.current=e})),t.current}class c extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},7865:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{G:()=>r})},260:(e,t,n)=>{"use strict";n.d(t,{Dt:()=>i,ys:()=>s});var r=n(6540),o=n(2413),a=n(7639);function s(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function i(){const{baseUrl:e}=(0,a.A)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.A,baseUrl:e})),[e])}},4245:(e,t,n)=>{"use strict";n.d(t,{Mq:()=>p,Tv:()=>u,a_:()=>m,gk:()=>g});var r=n(6540),o=n(1712),a=n(1062),s=n(6494),i=n(4799),c=n(4848);const l=r.createContext(void 0);function u(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,c.jsx)(l.Provider,{value:n,children:t})}function d(){const e=(0,r.useContext)(l);if(null==e)throw new i.dV("ScrollControllerProvider");return e}const f=()=>o.A.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=d(),o=(0,r.useRef)(f()),a=(0,i._q)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=f();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function m(){const e=d(),t=function(){const e=(0,r.useRef)({elem:null,top:0}),t=(0,r.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,r.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const r=t.getBoundingClientRect().top-n;return r&&window.scrollBy({left:0,top:r}),e.current={elem:null,top:0},{restored:0!==r}}),[]);return(0,r.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,r.useRef)(void 0),o=(0,r.useCallback)((r=>{t.save(r),e.disableScrollEvents(),n.current=()=>{const{restored:r}=t.restore();if(n.current=void 0,r){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,s.A)((()=>{queueMicrotask((()=>n.current?.()))})),{blockElementScrollPositionUntilNextRender:o}}function g(){const e=(0,r.useRef)(null),t=(0,a.A)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},1482:(e,t,n)=>{"use strict";n.d(t,{C:()=>r});const r="default"},9900:(e,t,n)=>{"use strict";n.d(t,{Wf:()=>u,Dv:()=>d});var r=n(6540);const o=JSON.parse('{"N":"localStorage","M":""}'),a=o.N;function s(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(e){if(void 0===e&&(e=a),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,c||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),c=!0),null}var t}let c=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function u(e,t){const n=`${e}${o.M}`;if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(n);const r=i(t?.persistence);return null===r?l:{get:()=>{try{return r.getItem(n)}catch(e){return console.error(`Docusaurus storage error, can't get key=${n}`,e),null}},set:e=>{try{const t=r.getItem(n);r.setItem(n,e),s({key:n,oldValue:t,newValue:e,storage:r})}catch(t){console.error(`Docusaurus storage error, can't set ${n}=${e}`,t)}},del:()=>{try{const e=r.getItem(n);r.removeItem(n),s({key:n,oldValue:e,newValue:null,storage:r})}catch(e){console.error(`Docusaurus storage error, can't delete key=${n}`,e)}},listen:e=>{try{const t=t=>{t.storageArea===r&&t.key===n&&e(t)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)}catch(t){return console.error(`Docusaurus storage error, can't listen for changes of key=${n}`,t),()=>{}}}}}function d(e,t){const n=(0,r.useRef)((()=>null===e?l:u(e,t))).current(),o=(0,r.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,r.useSyncExternalStore)(o,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},2098:(e,t,n)=>{"use strict";n.d(t,{o:()=>s});var r=n(7639),o=n(6347),a=n(4609);function s(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:s,currentLocale:i}}=(0,r.A)(),{pathname:c}=(0,o.zy)(),l=(0,a.Ks)(c,{trailingSlash:n,baseUrl:e}),u=i===s?e:e.replace(`/${i}/`,"/"),d=l.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===s?`${u}`:`${u}${e}/`}(n)}${d}`}}}},4067:(e,t,n)=>{"use strict";n.d(t,{$:()=>s});var r=n(6540),o=n(6347),a=n(4799);function s(e){const t=(0,o.zy)(),n=(0,a.ZC)(t),s=(0,a._q)(e);(0,r.useEffect)((()=>{n&&t!==n&&s({location:t,previousLocation:n})}),[s,t,n])}},6957:(e,t,n)=>{"use strict";n.d(t,{p:()=>o});var r=n(7639);function o(){return(0,r.A)().siteConfig.themeConfig}},6349:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});var r=n(7639);function o(){const{siteConfig:{themeConfig:e}}=(0,r.A)();return e}},2177:(e,t,n)=>{"use strict";n.d(t,{C:()=>i});var r=n(6540),o=n(7865),a=n(8180),s=n(6349);function i(){const{withBaseUrl:e}=(0,a.hH)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,s.c)();return(0,r.useCallback)((r=>{const a=new URL(r);if((0,o.G)(t,a.href))return r;const s=`${a.pathname+a.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(s,n))}),[e,t,n])}},4356:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addTrailingSlash=o,t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[s]=e.split(/[#?]/),i="/"===s||s===r?s:(c=s,l=n,l?o(c):a(c));var c,l;return e.replace(s,i)},t.addLeadingSlash=function(e){return(0,r.addPrefix)(e,"/")},t.removeTrailingSlash=a;const r=n(835);function o(e){return e.endsWith("/")?e:`${e}/`}function a(e){return(0,r.removeSuffix)(e,"/")}},8274:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=function e(t){if(t.cause)return[t,...e(t.cause)];return[t]}},4609:(e,t,n)=>{"use strict";t.rA=t.Ks=void 0;const r=n(1635);var o=n(4356);Object.defineProperty(t,"Ks",{enumerable:!0,get:function(){return r.__importDefault(o).default}});var a=n(835);var s=n(8274);Object.defineProperty(t,"rA",{enumerable:!0,get:function(){return s.getErrorCausalChain}})},835:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){if(""===t)return e;return e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},1513:(e,t,n)=>{"use strict";n.d(t,{zR:()=>w,TM:()=>j,yJ:()=>p,sC:()=>C,AO:()=>f});var r=n(8168);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;f--){var p=s[f];"."===p?a(s,f):".."===p?(a(s,f),d++):d&&(a(s,f),d--)}if(!l)for(;d--;d)s.unshift("..");!l||""===s[0]||s[0]&&o(s[0])||s.unshift("");var m=s.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var i=n(1561);function c(e){return"/"===e.charAt(0)?e:"/"+e}function l(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function p(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.A)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(i){throw i instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):i}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=s(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=p(e,t,g(),w.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(4363),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},s={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},i={};function c(e){return r.isMemo(e)?s:i[e.$$typeof]||o}i[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},i[r.Memo]=s;var l=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=p(n);o&&o!==m&&e(t,o,r)}var s=u(n);d&&(s=s.concat(d(n)));for(var i=c(t),g=c(n),h=0;h{"use strict";e.exports=function(e,t,n,r,o,a,s,i){if(!e){var c;if(void 0===t)c=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var l=[n,r,o,a,s,i],u=0;(c=new Error(t.replace(/%s/g,(function(){return l[u++]})))).name="Invariant Violation"}throw c.framesToPop=1,c}}},4634:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},5300:(e,t,n)=>{"use strict";n.r(t)},8252:(e,t,n)=>{"use strict";n.r(t)},5947:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function s(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),l=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,i((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),c(l,s(e,u,d)),1===e?(c(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){c(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,s=t.querySelector(r.barSelector),i=e?"-100":a(n.status||0),l=document.querySelector(r.parent);return c(s,{transition:"all 0 linear",transform:"translate3d("+i+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&p(o),l!=document.body&&u(l,"nprogress-custom-parent"),l.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var i=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),c=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function l(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),r=n+t;l(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=f(e);l(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},5302:(e,t,n)=>{var r=n(4634);e.exports=p,e.exports.parse=a,e.exports.compile=function(e,t){return i(a(e,t),t)},e.exports.tokensToFunction=i,e.exports.tokensToRegExp=f;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,s=0,i="",u=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],f=n[1],p=n.index;if(i+=e.slice(s,p),s=p+d.length,f)i+=f[1];else{var m=e[s],g=n[2],h=n[3],b=n[4],y=n[5],v=n[6],w=n[7];i&&(r.push(i),i="");var S=null!=g&&null!=m&&m!==g,x="+"===v||"*"===v,k="?"===v||"*"===v,E=n[2]||u,_=b||y;r.push({name:h||a++,prefix:g||"",delimiter:E,optional:k,repeat:x,partial:S,asterisk:!!w,pattern:_?l(_):w?".*":"[^"+c(E)+"]+?"})}}return s{Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json},9700:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var s=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,i=s.length;-1!==n.code.indexOf(o=t(r,i));)++i;return s[i]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function s(i){for(var c=0;c=a.length);c++){var l=i[c];if("string"==typeof l||l.content&&"string"==typeof l.content){var u=a[o],d=n.tokenStack[u],f="string"==typeof l?l:l.content,p=t(r,u),m=f.indexOf(p);if(m>-1){++o;var g=f.substring(0,m),h=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=f.substring(m+p.length),y=[];g&&y.push.apply(y,s([g])),y.push(h),b&&y.push.apply(y,s([b])),"string"==typeof l?i.splice.apply(i,[c,1].concat(y)):l.content=y}}else l.content&&s(l.content)}return i}(n.tokens)}}}})}(Prism)},6966:()=>{Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}},1255:(e,t,n)=>{var r={"./prism-json":2514,"./prism-sql":6966};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=1255},2694:(e,t,n)=>{"use strict";var r=n(6925);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,s){if(s!==r){var i=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw i.name="Invariant Violation",i}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},5556:(e,t,n)=>{e.exports=n(2694)()},6925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},2551:(e,t,n)=>{"use strict";var r=n(6540),o=n(9982);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n