diff --git a/Frontend/CO.CDP.OrganisationApp.Tests/CookieAcceptanceMiddlewareTests.cs b/Frontend/CO.CDP.OrganisationApp.Tests/CookieAcceptanceMiddlewareTests.cs
new file mode 100644
index 000000000..77f1eacc7
--- /dev/null
+++ b/Frontend/CO.CDP.OrganisationApp.Tests/CookieAcceptanceMiddlewareTests.cs
@@ -0,0 +1,74 @@
+using Moq;
+using Microsoft.AspNetCore.Http;
+
+namespace CO.CDP.OrganisationApp.Tests;
+
+public class CookieAcceptanceMiddlewareTests
+{
+    private readonly Mock<ICookiePreferencesService> _cookiePreferencesServiceMock;
+    private readonly Mock<RequestDelegate> _nextDelegateMock;
+    private readonly CookieAcceptanceMiddleware _middleware;
+    private readonly DefaultHttpContext _httpContext;
+
+    public CookieAcceptanceMiddlewareTests()
+    {
+        _cookiePreferencesServiceMock = new Mock<ICookiePreferencesService>();
+        _nextDelegateMock = new Mock<RequestDelegate>();
+        _middleware = new CookieAcceptanceMiddleware(_cookiePreferencesServiceMock.Object);
+        _httpContext = new DefaultHttpContext();
+    }
+
+    [Fact]
+    public async Task InvokeAsync_ShouldCallAccept_WhenQueryParameterIsTrue()
+    {
+        _httpContext.Request.QueryString = new QueryString($"?{CookieSettings.FtsHandoverParameter}=true");
+
+        await _middleware.InvokeAsync(_httpContext, _nextDelegateMock.Object);
+
+        _cookiePreferencesServiceMock.Verify(s => s.Accept(), Times.Once);
+        _nextDelegateMock.Verify(n => n(_httpContext), Times.Once);
+    }
+
+    [Fact]
+    public async Task InvokeAsync_ShouldCallReject_WhenQueryParameterIsFalse()
+    {
+        _httpContext.Request.QueryString = new QueryString($"?{CookieSettings.FtsHandoverParameter}=false");
+
+        await _middleware.InvokeAsync(_httpContext, _nextDelegateMock.Object);
+
+        _cookiePreferencesServiceMock.Verify(s => s.Reject(), Times.Once);
+        _nextDelegateMock.Verify(n => n(_httpContext), Times.Once);
+    }
+
+    [Fact]
+    public async Task InvokeAsync_ShouldCallReset_WhenQueryParameterIsUnknown()
+    {
+        _httpContext.Request.QueryString = new QueryString($"?{CookieSettings.FtsHandoverParameter}=unknown");
+
+        await _middleware.InvokeAsync(_httpContext, _nextDelegateMock.Object);
+
+        _cookiePreferencesServiceMock.Verify(s => s.Reset(), Times.Once);
+        _nextDelegateMock.Verify(n => n(_httpContext), Times.Once);
+    }
+
+    [Fact]
+    public async Task InvokeAsync_ShouldNotCallAnyMethod_WhenQueryParameterIsMissing()
+    {
+        await _middleware.InvokeAsync(_httpContext, _nextDelegateMock.Object);
+
+        _cookiePreferencesServiceMock.VerifyNoOtherCalls();
+        _nextDelegateMock.Verify(n => n(_httpContext), Times.Once);
+    }
+
+    [Fact]
+    public async Task InvokeAsync_ShouldNotCallAnyMethod_WhenQueryParameterHasInvalidValue()
+    {
+        _httpContext.Request.QueryString = new QueryString($"?{CookieSettings.FtsHandoverParameter}=invalid");
+
+        await _middleware.InvokeAsync(_httpContext, _nextDelegateMock.Object);
+
+        _cookiePreferencesServiceMock.VerifyNoOtherCalls();
+        _nextDelegateMock.Verify(n => n(_httpContext), Times.Once);
+    }
+}
+
diff --git a/Frontend/CO.CDP.OrganisationApp.Tests/CookiePreferencesServiceTests.cs b/Frontend/CO.CDP.OrganisationApp.Tests/CookiePreferencesServiceTests.cs
new file mode 100644
index 000000000..76f1d074c
--- /dev/null
+++ b/Frontend/CO.CDP.OrganisationApp.Tests/CookiePreferencesServiceTests.cs
@@ -0,0 +1,103 @@
+using Moq;
+using FluentAssertions;
+using Microsoft.AspNetCore.Http;
+
+namespace CO.CDP.OrganisationApp.Tests;
+
+public class CookiePreferencesServiceTests
+{
+    private readonly Mock<IHttpContextAccessor> _httpContextAccessorMock;
+    private readonly Mock<HttpContext> _httpContextMock;
+    private readonly Mock<HttpRequest> _httpRequestMock;
+    private readonly Mock<HttpResponse> _httpResponseMock;
+    private readonly Mock<IResponseCookies> _responseCookiesMock;
+    private readonly Mock<IRequestCookieCollection> _requestCookiesMock;
+    private readonly CookiePreferencesService _cookiePreferencesService;
+
+    public CookiePreferencesServiceTests()
+    {
+        _httpContextAccessorMock = new Mock<IHttpContextAccessor>();
+        _httpContextMock = new Mock<HttpContext>();
+        _httpRequestMock = new Mock<HttpRequest>();
+        _httpResponseMock = new Mock<HttpResponse>();
+        _responseCookiesMock = new Mock<IResponseCookies>();
+        _requestCookiesMock = new Mock<IRequestCookieCollection>();
+
+        _httpContextMock.Setup(c => c.Request).Returns(_httpRequestMock.Object);
+        _httpContextMock.Setup(c => c.Response).Returns(_httpResponseMock.Object);
+        _httpRequestMock.Setup(r => r.Cookies).Returns(_requestCookiesMock.Object);
+        _httpResponseMock.Setup(r => r.Cookies).Returns(_responseCookiesMock.Object);
+
+        _httpContextAccessorMock.Setup(a => a.HttpContext).Returns(_httpContextMock.Object);
+
+        _cookiePreferencesService = new CookiePreferencesService(_httpContextAccessorMock.Object);
+    }
+
+    [Fact]
+    public void Constructor_ShouldThrowException_WhenHttpContextIsNull()
+    {
+        var accessor = new Mock<IHttpContextAccessor>();
+        accessor.Setup(a => a.HttpContext).Returns((HttpContext)null!);
+
+        Action act = () => new CookiePreferencesService(accessor.Object);
+
+        act.Should().Throw<InvalidOperationException>()
+            .WithMessage("No active HTTP context.");
+    }
+
+    [Fact]
+    public void Accept_ShouldSetCookieWithAcceptValue()
+    {
+        _cookiePreferencesService.Accept();
+
+        _responseCookiesMock.Verify(c => c.Append(CookieSettings.CookieName, "Accept", It.IsAny<CookieOptions>()), Times.Once);
+        _cookiePreferencesService.GetValue().Should().Be(CookieAcceptanceValues.Accept);
+        _cookiePreferencesService.IsAccepted().Should().BeTrue();
+    }
+
+    [Fact]
+    public void Reject_ShouldSetCookieWithRejectValue()
+    {
+        _cookiePreferencesService.Reject();
+
+        _responseCookiesMock.Verify(c => c.Append(CookieSettings.CookieName, "Reject", It.IsAny<CookieOptions>()), Times.Once);
+        _cookiePreferencesService.GetValue().Should().Be(CookieAcceptanceValues.Reject);
+        _cookiePreferencesService.IsRejected().Should().BeTrue();
+    }
+
+    [Fact]
+    public void Reset_ShouldDeleteCookie_AndSetPendingValueToUnknown()
+    {
+        _cookiePreferencesService.Reset();
+
+        _responseCookiesMock.Verify(c => c.Delete(CookieSettings.CookieName), Times.Once);
+        _cookiePreferencesService.GetValue().Should().Be(CookieAcceptanceValues.Unknown);
+        _cookiePreferencesService.IsUnknown().Should().BeTrue();
+    }
+
+    [Fact]
+    public void GetValue_ShouldReturnPendingValue_WhenSet()
+    {
+        _cookiePreferencesService.Accept();
+
+        _cookiePreferencesService.GetValue().Should().Be(CookieAcceptanceValues.Accept);
+    }
+
+    [Fact]
+    public void GetValue_ShouldReturnValueFromRequestCookie_WhenNoPendingValue()
+    {
+        _requestCookiesMock.Setup(c => c.ContainsKey(CookieSettings.CookieName)).Returns(true);
+        _requestCookiesMock.Setup(c => c[CookieSettings.CookieName]).Returns("Reject");
+
+        _cookiePreferencesService.GetValue().Should().Be(CookieAcceptanceValues.Reject);
+    }
+
+    [Fact]
+    public void GetValue_ShouldReturnUnknown_WhenCookieIsNotPresent()
+    {
+        _requestCookiesMock.Setup(c => c.ContainsKey(CookieSettings.CookieName)).Returns(false);
+
+        _cookiePreferencesService.GetValue().Should().Be(CookieAcceptanceValues.Unknown);
+    }
+}
+
diff --git a/Frontend/CO.CDP.OrganisationApp.Tests/FtsUrlServiceTests.cs b/Frontend/CO.CDP.OrganisationApp.Tests/FtsUrlServiceTests.cs
index 03991869a..6de546262 100644
--- a/Frontend/CO.CDP.OrganisationApp.Tests/FtsUrlServiceTests.cs
+++ b/Frontend/CO.CDP.OrganisationApp.Tests/FtsUrlServiceTests.cs
@@ -4,16 +4,19 @@
 using FluentAssertions;
 
 namespace CO.CDP.OrganisationApp.Tests;
+
 public class FtsUrlServiceTests
 {
     private readonly Mock<IConfiguration> _configurationMock;
-    private readonly FtsUrlService _service;
+    private readonly Mock<ICookiePreferencesService> _cookiePreferencesService;
+    private readonly IFtsUrlService _service;
 
     public FtsUrlServiceTests()
     {
         _configurationMock = new Mock<IConfiguration>();
+        _cookiePreferencesService = new Mock<ICookiePreferencesService>();
         _configurationMock.Setup(c => c["FtsService"]).Returns("https://example.com/");
-        _service = new FtsUrlService(_configurationMock.Object);
+        _service = new FtsUrlService(_configurationMock.Object, _cookiePreferencesService.Object);
     }
 
     [Fact]
@@ -21,23 +24,23 @@ public void Constructor_ShouldThrowException_WhenFtsServiceIsNotConfigured()
     {
         _configurationMock.Setup(c => c["FtsService"]).Returns((string?)null);
 
-        Action action = () => new FtsUrlService(_configurationMock.Object);
+        Action action = () => new FtsUrlService(_configurationMock.Object, _cookiePreferencesService.Object);
 
         action.Should().Throw<InvalidOperationException>()
-                .WithMessage("FtsService is not configured.");
+            .WithMessage("FtsService is not configured.");
     }
 
     [Fact]
     public void BuildUrl_ShouldTrimTrailingSlashFromBaseServiceUrl()
     {
         _configurationMock.Setup(c => c["FtsService"]).Returns("https://example.com/");
-        var service = new FtsUrlService(_configurationMock.Object);
+        var service = new FtsUrlService(_configurationMock.Object, _cookiePreferencesService.Object);
         var endpoint = "test-endpoint";
         CultureInfo.CurrentUICulture = new CultureInfo("en-GB");
 
         var result = service.BuildUrl(endpoint);
 
-        result.Should().Be("https://example.com/test-endpoint?language=en_GB");
+        result.Should().Be("https://example.com/test-endpoint?language=en_GB&cookies_accepted=unknown");
     }
 
     [Fact]
@@ -48,18 +51,18 @@ public void BuildUrl_ShouldConstructCorrectUrl_WhenOnlyEndpointIsProvided()
 
         var result = _service.BuildUrl(endpoint);
 
-        result.Should().Be("https://example.com/test-endpoint?language=en_GB");
+        result.Should().Be("https://example.com/test-endpoint?language=en_GB&cookies_accepted=unknown");
     }
 
     [Fact]
-    public void BuildUrl_ShouldConstructCorrectUrl_WhenLanguageisWelsh()
+    public void BuildUrl_ShouldConstructCorrectUrl_WhenLanguageIsWelsh()
     {
         var endpoint = "test-endpoint";
         CultureInfo.CurrentUICulture = new CultureInfo("cy");
 
         var result = _service.BuildUrl(endpoint);
 
-        result.Should().Be("https://example.com/test-endpoint?language=cy");
+        result.Should().Be("https://example.com/test-endpoint?language=cy&cookies_accepted=unknown");
     }
 
     [Fact]
@@ -71,7 +74,7 @@ public void BuildUrl_ShouldIncludeOrganisationId_WhenProvided()
 
         var result = _service.BuildUrl(endpoint, organisationId);
 
-        result.Should().Be($"https://example.com/test-endpoint?language=en_GB&organisation_id={organisationId}");
+        result.Should().Be($"https://example.com/test-endpoint?language=en_GB&organisation_id={organisationId}&cookies_accepted=unknown");
     }
 
     [Fact]
@@ -83,12 +86,13 @@ public void BuildUrl_ShouldIncludeRedirectUrl_WhenProvided()
 
         var result = _service.BuildUrl(endpoint, null, redirectUrl);
 
-        result.Should().Be("https://example.com/test-endpoint?language=en_GB&redirect_url=%2Fredirect-path");
+        result.Should().Be("https://example.com/test-endpoint?language=en_GB&redirect_url=%2Fredirect-path&cookies_accepted=unknown");
     }
 
     [Fact]
     public void BuildUrl_ShouldIncludeAllParameters_WhenAllAreProvided()
     {
+        _cookiePreferencesService.Setup(c => c.GetValue()).Returns(CookieAcceptanceValues.Accept);
         var endpoint = "test-endpoint";
         var organisationId = Guid.NewGuid();
         var redirectUrl = "/redirect-path";
@@ -96,6 +100,21 @@ public void BuildUrl_ShouldIncludeAllParameters_WhenAllAreProvided()
 
         var result = _service.BuildUrl(endpoint, organisationId, redirectUrl);
 
-        result.Should().Be($"https://example.com/test-endpoint?language=en_GB&organisation_id={organisationId}&redirect_url=%2Fredirect-path");
+        result.Should().Be($"https://example.com/test-endpoint?language=en_GB&organisation_id={organisationId}&redirect_url=%2Fredirect-path&cookies_accepted=true");
+    }
+
+    [Theory]
+    [InlineData(CookieAcceptanceValues.Accept, "true")]
+    [InlineData(CookieAcceptanceValues.Reject, "false")]
+    [InlineData(CookieAcceptanceValues.Unknown, "unknown")]
+    public void BuildUrl_ShouldIncludeCookiesAcceptedParameter_BasedOnCookiePreferences(CookieAcceptanceValues preference, string expectedValue)
+    {
+        _cookiePreferencesService.Setup(c => c.GetValue()).Returns(preference);
+        var endpoint = "test-endpoint";
+        CultureInfo.CurrentUICulture = new CultureInfo("en-GB");
+
+        var result = _service.BuildUrl(endpoint);
+
+        result.Should().Be($"https://example.com/test-endpoint?language=en_GB&cookies_accepted={expectedValue}");
     }
 }
diff --git a/Frontend/CO.CDP.OrganisationApp/CookieAcceptanceMiddleware.cs b/Frontend/CO.CDP.OrganisationApp/CookieAcceptanceMiddleware.cs
new file mode 100644
index 000000000..7546418e5
--- /dev/null
+++ b/Frontend/CO.CDP.OrganisationApp/CookieAcceptanceMiddleware.cs
@@ -0,0 +1,27 @@
+namespace CO.CDP.OrganisationApp;
+
+public class CookieAcceptanceMiddleware(ICookiePreferencesService cookiePreferencesService) : IMiddleware
+{
+    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
+    {
+        if (context.Request.Query.TryGetValue(CookieSettings.FtsHandoverParameter, out var cookiesAcceptedValue))
+        {
+            string cookiesAccepted = cookiesAcceptedValue.ToString().ToLower();
+
+            switch (cookiesAccepted)
+            {
+                case "true":
+                    cookiePreferencesService.Accept();
+                    break;
+                case "false":
+                    cookiePreferencesService.Reject();
+                    break;
+                case "unknown":
+                    cookiePreferencesService.Reset();
+                    break;
+            }
+        }
+
+        await next(context);
+    }
+}
diff --git a/Frontend/CO.CDP.OrganisationApp/CookiePreferencesService.cs b/Frontend/CO.CDP.OrganisationApp/CookiePreferencesService.cs
new file mode 100644
index 000000000..840a10750
--- /dev/null
+++ b/Frontend/CO.CDP.OrganisationApp/CookiePreferencesService.cs
@@ -0,0 +1,91 @@
+namespace CO.CDP.OrganisationApp;
+
+public class CookiePreferencesService : ICookiePreferencesService
+{
+    private readonly HttpContext _context;
+
+    private CookieAcceptanceValues? pendingAcceptanceValue;
+
+    public CookiePreferencesService(IHttpContextAccessor httpContextAccessor)
+    {
+        _context = httpContextAccessor.HttpContext
+                    ?? throw new InvalidOperationException("No active HTTP context.");
+    }
+
+    public void Accept()
+    {
+        SetCookie(CookieAcceptanceValues.Accept);
+    }
+
+    public void Reject()
+    {
+        SetCookie(CookieAcceptanceValues.Reject);        
+    }
+
+    public void Reset()
+    {
+        _context.Response.Cookies.Delete(CookieSettings.CookieName);
+        pendingAcceptanceValue = CookieAcceptanceValues.Unknown;
+    }
+
+    private void SetCookie(CookieAcceptanceValues value)
+    {
+        _context.Response.Cookies.Append(CookieSettings.CookieName, value.ToString(), new CookieOptions
+        {
+            Expires = DateTimeOffset.UtcNow.AddDays(365),
+            IsEssential = true,
+            HttpOnly = true,
+            Secure = _context.Request.IsHttps
+        });
+        pendingAcceptanceValue = value;
+    }
+
+    public CookieAcceptanceValues GetValue()
+    {
+        if (pendingAcceptanceValue != null)
+        {
+            return (CookieAcceptanceValues)pendingAcceptanceValue;
+        }
+
+        if(_context.Request.Cookies.ContainsKey(CookieSettings.CookieName))
+        {
+            if (Enum.TryParse(typeof(CookieAcceptanceValues), _context.Request.Cookies[CookieSettings.CookieName], true, out var result))
+            {
+                return (CookieAcceptanceValues)result;
+            }
+        }
+
+        return CookieAcceptanceValues.Unknown;
+
+    }
+
+    public bool IsAccepted()
+    {
+        return GetValue() == CookieAcceptanceValues.Accept;
+    }
+
+    public bool IsRejected()
+    {
+        return GetValue() == CookieAcceptanceValues.Reject;
+    }
+
+    public bool IsUnknown()
+    {
+        return GetValue() == CookieAcceptanceValues.Unknown;
+    }
+}
+public enum CookieAcceptanceValues
+{
+    Unknown,
+    Accept,
+    Reject
+}
+
+public static class CookieSettings
+{
+    public const string CookieAcceptanceFieldName = "CookieAcceptance";
+    public const string CookieSettingsPageReturnUrlFieldName = "ReturnUrl";
+    public const string CookieBannerInteractionQueryString = "cookieBannerInteraction";
+    public const string CookieName = "SIRSI_COOKIES_PREFERENCES_SET";
+    public const string FtsHandoverParameter = "cookies_accepted";
+}
\ No newline at end of file
diff --git a/Frontend/CO.CDP.OrganisationApp/FtsUrlService.cs b/Frontend/CO.CDP.OrganisationApp/FtsUrlService.cs
index d6a512ab5..1410bb96c 100644
--- a/Frontend/CO.CDP.OrganisationApp/FtsUrlService.cs
+++ b/Frontend/CO.CDP.OrganisationApp/FtsUrlService.cs
@@ -1,17 +1,18 @@
 using Microsoft.AspNetCore.Http.Extensions;
 using System.Globalization;
-using System.Web;
 
 namespace CO.CDP.OrganisationApp;
 
 public class FtsUrlService : IFtsUrlService
 {
     private readonly string _ftsService;
+    private readonly ICookiePreferencesService _cookiePreferencesService;
 
-    public FtsUrlService(IConfiguration configuration)
+    public FtsUrlService(IConfiguration configuration, ICookiePreferencesService cookiePreferencesService)
     {
         var ftsService = configuration["FtsService"] ?? throw new InvalidOperationException("FtsService is not configured.");
         _ftsService = ftsService.TrimEnd('/');
+        _cookiePreferencesService = cookiePreferencesService;
     }
 
     public string BuildUrl(string endpoint, Guid? organisationId = null, string? redirectUrl = null)
@@ -36,13 +37,18 @@ public string BuildUrl(string endpoint, Guid? organisationId = null, string? red
             queryBuilder.Add("redirect_url", redirectUrl);
         }
 
+        CookieAcceptanceValues cookiesAccepted = _cookiePreferencesService.GetValue();
+        string cookiesAcceptedValue = cookiesAccepted switch
+        {
+            CookieAcceptanceValues.Accept => "true",
+            CookieAcceptanceValues.Reject => "false",
+            _ => "unknown"
+        };
+
+        queryBuilder.Add(CookieSettings.FtsHandoverParameter, cookiesAcceptedValue);
+
         uriBuilder.Query = queryBuilder.ToQueryString().Value;
 
         return uriBuilder.Uri.ToString();
     }
 }
-
-public interface IFtsUrlService
-{
-    string BuildUrl(string endpoint, Guid? organisationId = null, string? redirectUrl = null);
-}
\ No newline at end of file
diff --git a/Frontend/CO.CDP.OrganisationApp/ICookiePreferencesService.cs b/Frontend/CO.CDP.OrganisationApp/ICookiePreferencesService.cs
new file mode 100644
index 000000000..fce705800
--- /dev/null
+++ b/Frontend/CO.CDP.OrganisationApp/ICookiePreferencesService.cs
@@ -0,0 +1,12 @@
+namespace CO.CDP.OrganisationApp;
+
+public interface ICookiePreferencesService
+{
+    bool IsAccepted();
+    bool IsRejected();
+    void Accept();
+    void Reject();
+    void Reset();
+    bool IsUnknown();
+    CookieAcceptanceValues GetValue();
+}
\ No newline at end of file
diff --git a/Frontend/CO.CDP.OrganisationApp/IFtsUrlService.cs b/Frontend/CO.CDP.OrganisationApp/IFtsUrlService.cs
new file mode 100644
index 000000000..068501e2a
--- /dev/null
+++ b/Frontend/CO.CDP.OrganisationApp/IFtsUrlService.cs
@@ -0,0 +1,6 @@
+namespace CO.CDP.OrganisationApp;
+
+public interface IFtsUrlService
+{
+    string BuildUrl(string endpoint, Guid? organisationId = null, string? redirectUrl = null);
+}
\ No newline at end of file
diff --git a/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml b/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml
index fd1a24641..f6630a0b2 100644
--- a/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml
+++ b/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml
@@ -4,6 +4,8 @@
 @using CO.CDP.Localization
 @using Microsoft.AspNetCore.Mvc.Localization
 
+@inject ICookiePreferencesService cookiePreferencesService;
+
 @{
     ViewData["Title"] = StaticTextResource.Supplementary_Cookies_Title;
     var hasError = ((TagBuilder)Html.ValidationMessageFor(m => m.CookieAcceptance)).HasInnerHtml;
@@ -45,13 +47,13 @@
 
                 <div class="govuk-radios govuk-!-margin-bottom-8" data-module="govuk-radios">
                     <div class="govuk-radios__item">
-                        <input class="govuk-radios__input" id="@nameof(Model.CookieAcceptance)" name="@nameof(Model.CookieAcceptance)" type="radio" value="@CookieAcceptanceValues.Accept" checked="@Model.RadioIsChecked(CookieAcceptanceValues.Accept)">
+                        <input class="govuk-radios__input" id="@nameof(Model.CookieAcceptance)" name="@nameof(Model.CookieAcceptance)" type="radio" value="@CookieAcceptanceValues.Accept" checked="@cookiePreferencesService.IsAccepted()">
                         <label class="govuk-label govuk-radios__label" for="@nameof(Model.CookieAcceptance)">
                             @StaticTextResource.Supplementary_Cookies_UseCookies
                         </label>
                     </div>
                     <div class="govuk-radios__item">
-                        <input class="govuk-radios__input" id="@nameof(Model.CookieAcceptance)-1" name="@nameof(Model.CookieAcceptance)" type="radio" value="@CookieAcceptanceValues.Reject" checked="@Model.RadioIsChecked(CookieAcceptanceValues.Reject)">
+                    <input class="govuk-radios__input" id="@nameof(Model.CookieAcceptance)-1" name="@nameof(Model.CookieAcceptance)" type="radio" value="@CookieAcceptanceValues.Reject" checked="@cookiePreferencesService.IsRejected()">
                         <label class="govuk-label govuk-radios__label" for="@nameof(Model.CookieAcceptance)-1">
                             @StaticTextResource.Supplementary_Cookies_DoNotUseCookies
                         </label>
diff --git a/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml.cs b/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml.cs
index 7e49df3bc..5a25ae200 100644
--- a/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml.cs
+++ b/Frontend/CO.CDP.OrganisationApp/Pages/Cookies.cshtml.cs
@@ -7,8 +7,8 @@ namespace CO.CDP.OrganisationApp.Pages;
 
 [AuthenticatedSessionNotRequired]
 public class CookiesModel(
-    IWebHostEnvironment env,
-    IFlashMessageService flashMessageService) : PageModel
+    IFlashMessageService flashMessageService,
+    ICookiePreferencesService cookiePreferencesService) : PageModel
 {
     [BindProperty]
     [Required(ErrorMessage="Choose whether you accept cookies that measure website use")]
@@ -36,43 +36,24 @@ public IActionResult OnPost()
             return Page();
         }
 
-        Response.Cookies.Append(CookieSettings.CookieName, ((int)CookieAcceptance).ToString(), new CookieOptions{
-            Expires = DateTimeOffset.UtcNow.AddDays(365),
-            IsEssential = true,
-            HttpOnly = false,
-            Secure = !env.IsDevelopment()
-        });
+        switch(CookieAcceptance)
+        {
+            case CookieAcceptanceValues.Accept:
+                cookiePreferencesService.Accept();
+            break;
+
+            case CookieAcceptanceValues.Reject:
+                cookiePreferencesService.Reject();
+            break;
+        }
 
         if (!string.IsNullOrEmpty(ReturnUrl) && Url.IsLocalUrl(ReturnUrl))
         {
-            return LocalRedirect(QueryHelpers.AddQueryString(ReturnUrl, CookieSettings.CookiesAcceptedQueryString, "true"));
+            return LocalRedirect(QueryHelpers.AddQueryString(ReturnUrl, CookieSettings.CookieBannerInteractionQueryString, "true"));
         }
+
         flashMessageService.SetFlashMessage(FlashMessageType.Success, "You’ve set your cookie preferences.");
         
         return RedirectToPage("/Cookies");
     }
-
-    public bool RadioIsChecked(CookieAcceptanceValues value)
-    {
-        return Request.Cookies.ContainsKey(CookieSettings.CookieName) && Request.Cookies[CookieSettings.CookieName] == ((int)value).ToString();
-    }
-}
-
-public enum CookieAcceptanceValues
-{
-    Accept=1,
-    Reject=2
-}
-
-public static class CookieSettings
-{
-    public const string CookieAcceptanceFieldName = "CookieAcceptance";
-    public const string CookieSettingsPageReturnUrlFieldName = "ReturnUrl";
-    public const string CookiesAcceptedQueryString = "cookiesAccepted";
-
-    // Cookie name in FTS is FT_COOKIES_PREFERENCES_SET
-    // Cookie values have been configured to match (See the 1 and 2 in the CookieAcceptanceValues enum).
-    // So if we're sharing a domain in production,we could switch to using the same cookie name and remove the frontend page
-    // (But keep the post handler for setting it - otherwise our cookie banner would need to post across to their subdomain)
-    public const string CookieName = "SIRSI_COOKIES_PREFERENCES_SET";
 }
\ No newline at end of file
diff --git a/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_CookieBanner.cshtml b/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_CookieBanner.cshtml
index 2ed94f1e9..1f15fb4d5 100644
--- a/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_CookieBanner.cshtml
+++ b/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_CookieBanner.cshtml
@@ -1,8 +1,18 @@
+@using Microsoft.AspNetCore.Http.Extensions;
+@using Microsoft.AspNetCore.Http;
+@using Microsoft.AspNetCore.WebUtilities;
+@inject ICookiePreferencesService cookiePreferencesService;
+
 @{
-    string currentUrl = Context.Request.PathBase + Context.Request.Path + Context.Request.QueryString;
+    var queryDict = QueryHelpers.ParseQuery(Context.Request.QueryString.Value);
+    queryDict.Remove(CookieSettings.FtsHandoverParameter);
+    var queryBuilder = new QueryBuilder(queryDict);
+    QueryString updatedQueryString = queryBuilder.ToQueryString();
+    string currentUrl = Context.Request.PathBase + Context.Request.Path + updatedQueryString;
 }
 
-@if (!Context.Request.Cookies.ContainsKey(CookieSettings.CookieName) && !Context.Request.Path.StartsWithSegments("/cookies")) {
+@if (cookiePreferencesService.IsUnknown() && !Context.Request.Query.ContainsKey(CookieSettings.CookieBannerInteractionQueryString) && !Context.Request.Path.StartsWithSegments("/cookies"))
+{
     <div class="govuk-cookie-banner" data-nosnippet role="region" aria-label="Cookies on Find a Tender">
         <div class="govuk-cookie-banner__message govuk-width-container">
             <div class="govuk-grid-row">
@@ -32,9 +42,9 @@
     </div>
 }
 
-@if (Context.Request.Cookies.ContainsKey(CookieSettings.CookieName) && Context.Request.Query.ContainsKey(CookieSettings.CookiesAcceptedQueryString))
+@if (!cookiePreferencesService.IsUnknown() && Context.Request.Query.ContainsKey(CookieSettings.CookieBannerInteractionQueryString))
 {
-    var acceptedState = (Context.Request.Cookies.ContainsKey(CookieSettings.CookieName) && Context.Request.Cookies[CookieSettings.CookieName] == ((int)CookieAcceptanceValues.Accept).ToString()) ? "accepted" : "rejected";
+    var acceptedState = cookiePreferencesService.IsAccepted() ? "accepted" : "rejected";
     <div class="govuk-cookie-banner" data-nosnippet role="region" aria-label="Cookies on Find a Tender">
         <div class="govuk-cookie-banner__message govuk-width-container">
             <div class="govuk-grid-row">
@@ -47,7 +57,7 @@
             <div class="govuk-button-group">
                 @{
                     var currentQueryString = Context.Request.QueryString.ToString();
-                    var cleanedQueryString = currentQueryString.Replace($"{CookieSettings.CookiesAcceptedQueryString}=true", "");
+                    var cleanedQueryString = currentQueryString.Replace($"{CookieSettings.CookieBannerInteractionQueryString}=true", "");
                     cleanedQueryString = cleanedQueryString == "?" ? "" : cleanedQueryString;
                 }
                 <a class="govuk-button" role="button" data-module="govuk-button" href="@(Context.Request.PathBase + Context.Request.Path + cleanedQueryString)">Hide cookie message</a>
diff --git a/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_Layout.cshtml b/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_Layout.cshtml
index ea3437209..72f1c06d9 100644
--- a/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_Layout.cshtml
+++ b/Frontend/CO.CDP.OrganisationApp/Pages/Shared/_Layout.cshtml
@@ -5,6 +5,7 @@
 
 @inject Microsoft.Extensions.Configuration.IConfiguration config
 @inject IUserInfoService userInfoService
+@inject ICookiePreferencesService cookiePreferencesService;
 @inject IHtmlLocalizer<StaticTextResource> Localizer
 @inject IFtsUrlService FtsUrlService
 
@@ -14,8 +15,7 @@
     @{
         var googleTagId = config["GoogleTagId"];
         if (!string.IsNullOrWhiteSpace(googleTagId)
-        && Context.Request.Cookies.ContainsKey(CookieSettings.CookieName)
-        && Context.Request.Cookies[CookieSettings.CookieName] == ((int)CookieAcceptanceValues.Accept).ToString())
+        && cookiePreferencesService.IsAccepted())
         {
             <!-- Google tag (gtag.js) -->
             <script async src="https://www.googletagmanager.com/gtag/js?id=@googleTagId"></script>
diff --git a/Frontend/CO.CDP.OrganisationApp/Program.cs b/Frontend/CO.CDP.OrganisationApp/Program.cs
index 944b54b21..8a320e952 100644
--- a/Frontend/CO.CDP.OrganisationApp/Program.cs
+++ b/Frontend/CO.CDP.OrganisationApp/Program.cs
@@ -218,6 +218,8 @@
 builder.Services.AddSingleton<IAuthorizationMiddlewareResultHandler, CustomAuthorizationMiddlewareResultHandler>();
 builder.Services.AddAuthorization();
 
+builder.Services.AddScoped<CookieAcceptanceMiddleware>();
+builder.Services.AddScoped<ICookiePreferencesService, CookiePreferencesService>();
 builder.Services.AddScoped<IFlashMessageService, FlashMessageService>();
 
 builder.Services.AddHealthChecks();
@@ -230,6 +232,7 @@
 var app = builder.Build();
 app.UseForwardedHeaders();
 app.UseMiddleware<ExceptionMiddleware>();
+app.UseMiddleware<CookieAcceptanceMiddleware>();
 
 // Configure the HTTP request pipeline.
 if (!app.Environment.IsDevelopment())