Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      CodeSOD: Functionally, a Date

      September 16, 2025

      Creating Elastic And Bounce Effects With Expressive Animator

      September 16, 2025

      Microsoft shares Insiders preview of Visual Studio 2026

      September 16, 2025

      From Data To Decisions: UX Strategies For Real-Time Dashboards

      September 13, 2025

      DistroWatch Weekly, Issue 1139

      September 14, 2025

      Building personal apps with open source and AI

      September 12, 2025

      What Can We Actually Do With corner-shape?

      September 12, 2025

      Craft, Clarity, and Care: The Story and Work of Mengchu Yao

      September 12, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Can I use React Server Components (RSCs) today?

      September 16, 2025
      Recent

      Can I use React Server Components (RSCs) today?

      September 16, 2025

      Perficient Named among Notable Providers in Forrester’s Q3 2025 Commerce Services Landscape

      September 16, 2025

      Sarah McDowell Helps Clients Build a Strong AI Foundation Through Salesforce

      September 16, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured

      I Ran Local LLMs on My Android Phone

      September 16, 2025
      Recent

      I Ran Local LLMs on My Android Phone

      September 16, 2025

      DistroWatch Weekly, Issue 1139

      September 14, 2025

      sudo vs sudo-rs: What You Need to Know About the Rust Takeover of Classic Sudo Command

      September 14, 2025
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»Personalized Optimizely CMS Website Search Experiences Azure AI Search & Personalizer

    Personalized Optimizely CMS Website Search Experiences Azure AI Search & Personalizer

    April 10, 2025
    Personalized Optimizely CMS Website Search Experiences Azure AI Search & Personalizer

    In the last blog, we discussed Integrating the Optimizely CMS website with Azure AI search. Now let’s take a bit more advanced topic to serve Personalization experience with Azure AI search with Azure personalizer. Together, they enable you to serve dynamic customized content and search results across user  behaviour, preferences, and context.

    What is Azure Personalizer?

    Azure Personalizer Cognitive Service for Real-time Association using Reinforcement Learning. It gives you the ability to serve content or experiences that are most relevant to a user — informed by past behaviour and current context.

    Benefits of AI Personalizer:

    • So it can study and evolve as people engage with it.
    • Amazingly helpful for ranking search results.
    • Can customize direct calls to action, highlighted articles, or goods.

    How It Works with Azure AI Search and Optimizely

    1. The user performs a search on your Optimizely site.
    2. Azure AI Search simply gives a  list of matching documents
    3. These documents are sent to Azure Personalizer as “rankable actions.”
    4. The personalized orders results using the context of the user.
    5. Your app serves personalized results and the user’s feedback helps Personalizer to learn & evolve further.

    Set Up Azure Personalizer

    • Navigate to Azure Portal → Personalizer resource creation
    • Save your endpoint and API key.
    • In step 3, specify the Content that you want to be ranked (i.e., search results)

    Integration Code

    Model for Rankable Action

    public class RankableDocument
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public string Summary { get; set; }
        public string Category { get; set; }
    }

    Send Info to Personalizer with Context:

    private object GetUserContext(HttpRequestBase request)
    {
        return new
        {
            timeOfDay = DateTime.Now.Hour,
            device = request.Browser.IsMobileDevice ? "mobile" : "desktop",
            userAgent = request.UserAgent,
            language = request.UserLanguages?.FirstOrDefault() ?? "en"
        };
    }
    public async Task<List<RankableDocument>> GetPersonalizedResultsAsync(List<RankableDocument> documents, string userId)
    {
        var contextFeatures = new[] { GetUserContext(Request) };
    
        var actions = documents.Select(doc => new
        {
            id = doc.Id,
            features = new[]
            {
                new { category = doc.Category },
                new { title = doc.Title }
            }
        });
    
        _eventId = Guid.NewGuid().ToString();
    
        var request = new
        {
            contextFeatures = contextFeatures,
            actions = actions,
            excludedActions = new string[] {},
            eventId = _eventId,
            deferActivation = false
        };
    
        var client = new HttpClient();
        client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "--YOUR API KEY ---");
        var response = await client.PostAsync("--Endpoint--/personalizer/v1.0/rank",
            new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"));
    
        var result = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
        var topActionId = result.RootElement.GetProperty("rewardActionId").GetString();
    
        return documents.OrderByDescending(d => d.Id == topActionId).ToList();
    }

    Now let’s consider our previous example of search page controller & view and extend it

    Search Controller

    public class AzureSearchPageController : PageController<AzureSearchPage>
    {
        private static string _eventId;
    
        public async Task<ActionResult> Index(AzureSearchPage currentPage, string q = "")
        {
            var results = new List<RankableDocument>();
    
            if (!string.IsNullOrEmpty(q))
            {
                var url = $"https://<search-service>.search.windows.net/indexes/<index-name>/docs?api-version=2021-04-30-Preview&search={q}";
                using var client = new HttpClient();
                client.DefaultRequestHeaders.Add("api-key", "<your-query-key>");
                var response = await client.GetStringAsync(url);
    
                var doc = JsonDocument.Parse(response);
                results = doc.RootElement.GetProperty("value")
                    .EnumerateArray()
                    .Select(x => new RankableDocument
                    {
                        Id = x.GetProperty("id").GetString(),
                        Title = x.GetProperty("name").GetString(),
                        Category = x.GetProperty("type").GetString(),
                        Summary = x.GetProperty("content").GetString()
                    }).ToList();
    
                results = await GetPersonalizedResultsAsync(results, "user123");
            }
    
            ViewBag.Results = results;
            ViewBag.Query = q;
            ViewBag.EventId = _eventId;
            return View(currentPage);
        }
    
        [HttpPost]
        public async Task<ActionResult> Reward(string eventId, double rewardScore)
        {
            using var client = new HttpClient();
            client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "<your-api-key>");
    
            var rewardUrl = $"<your-endpoint>/personalizer/v1.0/events/{eventId}/reward";
            var result = await client.PostAsync(rewardUrl, new StringContent(rewardScore.ToString(), Encoding.UTF8, "application/json"));
    
            return Json(new { success = result.IsSuccessStatusCode });
        }
    }

    Search Page View

    @model AzureSearchPage
    <h1>Personalized Search Results</h1>
    <form method="get">
        <input type="text" name="q" value="@ViewBag.Query" placeholder="Search..." />
        <button type="submit">Search</button>
    </form>
    
    <ul>
    @foreach (var result in ViewBag.Results as List<RankableDocument>)
    {
        <li>
            <h4>@result.Title</h4>
            <p>@result.Summary</p>
            <button onclick="sendReward('@ViewBag.EventId', 1.0)">Like</button>
            <button onclick="sendReward('@ViewBag.EventId', 0.0)">Not Relevant</button>
        </li>
    }
    </ul>
    <script>
    function sendReward(eventId, score) {
        fetch('/AzureSearchPage/Reward', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ eventId: eventId, rewardScore: score })
        }).then(r => {
            if (r.ok) alert("Thanks! Your feedback was recorded.");
        });
    }
    </script>

    With Azure AI Search delivering relevant results and Azure Personalizer re-ranking them based on real-time context, your Optimizely site becomes an intelligent experience engine.

    This blog has also been published here.

    Source: Read More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleAgents bring the role of AI in development from reactive to proactive
    Next Article Android Development Codelab: Mastering Advanced Concepts

    Related Posts

    Development

    Can I use React Server Components (RSCs) today?

    September 16, 2025
    Development

    Perficient Named among Notable Providers in Forrester’s Q3 2025 Commerce Services Landscape

    September 16, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    I’ve reviewed a lot of tech, and these 9 products are even easier to recommend now thanks to Amazon Prime Day deals

    News & Updates

    CVE-2025-6916 – TOTOLINK T6 Local Network Authentication Bypass

    Common Vulnerabilities and Exposures (CVEs)

    Opera 120 brings built-in translation and smarter split screen

    Operating Systems

    Quadrapassel – falling-block game

    Linux

    Highlights

    CVE-2025-37992 – Linux Kernel net_sched NULL Pointer Dereference Vulnerability

    May 26, 2025

    CVE ID : CVE-2025-37992

    Published : May 26, 2025, 3:15 p.m. | 1 hour, 42 minutes ago

    Description : In the Linux kernel, the following vulnerability has been resolved:

    net_sched: Flush gso_skb list too during ->change()

    Previously, when reducing a qdisc’s limit via the ->change() operation, only
    the main skb queue was trimmed, potentially leaving packets in the gso_skb
    list. This could result in NULL pointer dereference when we only check
    sch->limit against sch->q.qlen.

    This patch introduces a new helper, qdisc_dequeue_internal(), which ensures
    both the gso_skb list and the main queue are properly flushed when trimming
    excess packets. All relevant qdiscs (codel, fq, fq_codel, fq_pie, hhf, pie)
    are updated to use this helper in their ->change() routines.

    Severity: 0.0 | NA

    Visit the link for more details, such as CVSS details, affected products, timeline, and more…

    CVE-2025-4412 – Viscosity macOS Launch Agent Dynamic Library Loading Vulnerability

    May 27, 2025

    Rilasciata SparkyLinux 7.8: Una Distribuzione GNU/Linux Leggera e Versatile

    July 16, 2025

    My best Helldivers 2 Illuminate loadout is completely insane, but I promise it works — use this in the new update and forget about the latest Warbond

    May 15, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.