diff --git a/src/client/components/facet_results/ApexCharts.js b/src/client/components/facet_results/ApexCharts.js
index 73ca7496bdf803547209fcda55709fbac7de84e8..70a2648cceac0a6cb64974a08dcdba11610f6cf4 100644
--- a/src/client/components/facet_results/ApexCharts.js
+++ b/src/client/components/facet_results/ApexCharts.js
@@ -123,7 +123,8 @@ class ApexChart extends React.Component {
         this.state.createChartData({
           ...this.props,
           resultClassConfig: this.state.resultClassConfig,
-          chartTypeObj
+          chartTypeObj,
+          fetchInstanceAnalysis: this.props.fetchInstanceAnalysis
         })
       )
       this.chart.render()
diff --git a/src/client/components/facet_results/ResultClassRoute.js b/src/client/components/facet_results/ResultClassRoute.js
index be8cd4787ddbe6c834b3b7fa5a4df9aafb8d96e7..200b090d977fede203058994f5810cae0ddca65f 100644
--- a/src/client/components/facet_results/ResultClassRoute.js
+++ b/src/client/components/facet_results/ResultClassRoute.js
@@ -261,7 +261,9 @@ const ResultClassRoute = props => {
         results: perspectiveState.results,
         fetching: perspectiveState.fetching,
         resultUpdateID: perspectiveState.resultUpdateID,
+        fetchInstanceAnalysis: props.fetchInstanceAnalysis,
         instanceAnalysisDataUpdateID: perspectiveState.instanceAnalysisDataUpdateID,
+        instanceAnalysisData: perspectiveState.instanceAnalysisData,
         facetUpdateID: facetState ? facetState.facetUpdateID : null,
         fetchData: props.fetchResults
       }
diff --git a/src/client/library_configs/ApexCharts/ApexChartsConfig.js b/src/client/library_configs/ApexCharts/ApexChartsConfig.js
index bf51863b10e4e8d87c659ecd9490e1e397fbcca3..d2fa91aff1e04f7f5997fd390276630bc76b5b81 100644
--- a/src/client/library_configs/ApexCharts/ApexChartsConfig.js
+++ b/src/client/library_configs/ApexCharts/ApexChartsConfig.js
@@ -329,3 +329,154 @@ const apexBarChartOptions = {
     }
   }
 }
+
+export const createApexTimelineChartData = ({
+  resultClass,
+  facetClass,
+  perspectiveState,
+  results,
+  resultClassConfig,
+  screenSize,
+  fetchInstanceAnalysis
+}) => {
+  const {
+    xaxisTitle,
+    yaxisTitle
+  } = resultClassConfig
+  let min
+  let max
+  if (results && results.length > 0) {
+    preprocessTimelineData(results)
+    min = new Date(results[0].beginDate).getTime()
+    max = new Date(results[results.length - 1].endDate).getTime()
+  }
+  const apexChartOptionsWithData = {
+    ...timelineOptions,
+    chart: {
+      type: 'rangeBar',
+      width: '100%',
+      height: '100%',
+      events: {
+        click: (event, chartContext, config) => {
+          if (chartContext.w.globals.initialSeries[config.seriesIndex]) {
+            const data = chartContext.w.globals.initialSeries[config.seriesIndex].data[config.dataPointIndex]
+            fetchInstanceAnalysis({
+              resultClass: `${resultClass}Dialog`,
+              facetClass,
+              period: data.period,
+              province: data.id
+            })
+          }
+        },
+        beforeResetZoom: (chartContext, opts) => {
+          return { xaxis: { min, max } }
+        }
+      }
+    },
+    xaxis: {
+      ...timelineOptions.xaxis,
+      title: {
+        text: xaxisTitle
+      },
+      min,
+      max
+    },
+    yaxis: { title: { text: yaxisTitle } },
+    series: results
+  }
+  return apexChartOptionsWithData
+}
+
+const timelineOptions = {
+  plotOptions: {
+    bar: {
+      horizontal: true,
+      barHeight: '70%'
+      // rangeBarGroupRows: true
+    }
+  },
+  colors: [
+    '#008FFB', '#00E396', '#FEB019', '#FF4560', '#775DD0',
+    '#3F51B5', '#546E7A', '#D4526E', '#8D5B4C', '#F86624',
+    '#D7263D', '#1B998B', '#2E294E', '#F46036', '#E2C044'
+  ],
+  fill: {
+    type: 'solid'
+  },
+  xaxis: {
+    type: 'datetime',
+    labels: {
+      formatter: value => {
+        return new Date(value).getFullYear()
+      }
+    }
+  },
+  legend: {
+    position: 'top'
+  },
+  tooltip: {
+    custom: opts => {
+      const data = opts.w.globals.initialSeries[opts.seriesIndex].data[opts.dataPointIndex]
+      const { ylabel, seriesName } = opts.ctx.rangeBar.getTooltipValues(opts)
+      // const startYear = new Date(opts.y1).getFullYear()
+      // const endYear = new Date(opts.y2).getFullYear()
+      return `
+      <div class="apexcharts-custom-tooltip">
+        <p><b>Maakunta:</b> ${ylabel.replace(':', '')}</p>
+        <p><b>Aikakausi:</b> ${seriesName.replace(':', '')}</p>
+        <p><b>Löytöjen lukumäärä:</b> ${data.instanceCount}</p> 
+      </div>  
+    `
+    }
+    // fixed: {
+    //   enabled: true,
+    //   position: 'topLeft',
+    //   offsetX: 0,
+    //   offsetY: 0
+    // }
+  },
+  grid: {
+    borderColor: '#000',
+    // row: {
+    //   opacity: 0
+    // },
+    padding: {
+      right: 15
+    }
+  }
+}
+
+const preprocessTimelineData = rawData => {
+  const lengths = []
+  rawData.sort((a, b) => new Date(a.beginDate) - new Date(b.beginDate) || new Date(a.endDate) - new Date(b.endDate))
+  rawData.forEach((obj, index) => {
+    if (!Array.isArray(obj.data)) { obj.data = [obj.data] }
+    obj.data.forEach(dataObj => {
+      dataObj.y = [
+        new Date(obj.beginDate).getTime(),
+        new Date(obj.endDate).getTime()
+      ]
+    })
+    obj.data.sort((a, b) => a.x.localeCompare(b.x))
+    lengths.push({ index, length: obj.data.length })
+  })
+  lengths.sort((a, b) => b.length - a.length)
+  if (rawData[0].data.length < lengths[0].length) {
+    const indexOfLongestArr = lengths[0].index
+    /*
+    * The first data array must hold all possible values,
+    * because it is used for sortable y-axis.
+    */
+    rawData[indexOfLongestArr].data.forEach((obj, index) => {
+      if (!rawData[0].data.find(x => x.id === obj.id)) {
+        rawData[0].data.push({
+          id: obj.id,
+          x: obj.x,
+          y: [null, null],
+          instanceCount: 0
+        })
+      }
+    })
+  }
+  rawData[0].data.sort((a, b) => a.x.localeCompare(b.x))
+}
diff --git a/src/server/index.js b/src/server/index.js
index f9d47252436461afee63dbb4a7242521dfd2eccd..3a0661e8c71dd29018f775524431910fcbfec211 100644
--- a/src/server/index.js
+++ b/src/server/index.js
@@ -105,7 +105,9 @@ createBackendSearchConfig().then(backendSearchConfig => {
         limit: body.limit,
         optimize: body.optimize,
         fromID: body.fromID,
-        toID: body.toID
+        toID: body.toID,
+        period: body.period,
+        province: body.province
       })
       if (resultFormat === 'csv') {
         res.writeHead(200, {
diff --git a/src/server/sparql/FacetResults.js b/src/server/sparql/FacetResults.js
index f59171d26305624d768344ff9e34c2be487af22c..27dbb4dd1ae5493865d2b7d802793a40478334f0 100644
--- a/src/server/sparql/FacetResults.js
+++ b/src/server/sparql/FacetResults.js
@@ -103,7 +103,9 @@ export const getAllResults = ({
   optimize,
   limit,
   fromID = null,
-  toID = null
+  toID = null,
+  period = null,
+  province = null
 }) => {
   const finalPerspectiveID = perspectiveID || facetClass
   const perspectiveConfig = backendSearchConfig[finalPerspectiveID]
@@ -164,6 +166,12 @@ export const getAllResults = ({
   if (toID) {
     q = q.replace(/<TO_ID>/g, `<${toID}>`)
   }
+  if (period) {
+    q = q.replace(/<PERIOD>/g, `<${period}>`)
+  }
+  if (province) {
+    q = q.replace(/<PROVINCE>/g, `<${province}>`)
+  }
   if (property) {
     q = q.replace(/<PROPERTY>/g, property)
   }