diff --git a/packages/fcl-web/src/fphtml.pp b/packages/fcl-web/src/fphtml.pp
index 4cffb914d6..551d4f4b30 100644
--- a/packages/fcl-web/src/fphtml.pp
+++ b/packages/fcl-web/src/fphtml.pp
@@ -46,6 +46,27 @@ type
   TWriterEvent = procedure (Sender:THTMLContentProducer; aWriter : THTMLWriter) of object;
   TBooleanEvent = procedure (Sender:THTMLContentProducer; var flag : boolean) of object;
 
+  { THTMLCustomPagContentProducer }
+
+  { THTMLCustomPageContentProducer }
+
+  THTMLCustomPageContentProducer = class (THTMLContentProducer)
+  private
+    FOnWritePage: TWriterEvent;
+  protected
+    function WriteContent (aWriter : THTMLWriter) : THTMLCustomElement; override;
+    procedure DoWritePage (aWriter : THTMLWriter); virtual;
+  public
+    Property OnWritePage : TWriterEvent read FOnWritePage write FOnWritePage;
+  end;
+
+  { THTMLCustomPagContentProducer }
+
+  THTMLPageContentProducer = class (THTMLCustomPageContentProducer)
+  published
+    Property OnWritePage;
+  end;
+
   { THTMLCustomDatasetContentProducer }
 
   THTMLCustomDatasetContentProducer = class (THTMLContentProducer)
@@ -471,5 +492,21 @@ begin
     FOnGetContent(Self,ARequest,HTMLPage,Handled);
 end;
 
+{ THTMLCustomPageContentProducer }
+
+function THTMLCustomPageContentProducer.WriteContent(aWriter: THTMLWriter
+  ): THTMLCustomElement;
+begin
+  result := aWriter.Starthtml;
+  DoWritePage(aWriter);
+  aWriter.Endhtml;
+end;
+
+procedure THTMLCustomPageContentProducer.DoWritePage(aWriter: THTMLWriter);
+begin
+  if assigned (FOnWritePage) then
+    FOnWritePage (self, aWriter);
+end;
+
 end.