diff --git a/scripts/ci/jobs/code-coverage.yml b/scripts/ci/jobs/code-coverage.yml
index fc95559ae5d3ec245be445e9ba989ea616a291c0..ac68e457ea9e42821953606ecb735be0d10d8b8f 100644
--- a/scripts/ci/jobs/code-coverage.yml
+++ b/scripts/ci/jobs/code-coverage.yml
@@ -21,13 +21,14 @@ code coverage:
     - genhtml --demangle-cpp -o coverage_report coverage.info
     - wget https://raw.github.com/eriwen/lcov-to-cobertura-xml/master/lcov_cobertura/lcov_cobertura.py
     - poetry run python lcov_cobertura.py coverage.info --base-dir $CI_PROJECT_DIR
+    - poetry run ./generate_coverage_vis_data.py
   artifacts:
-    expose_as: 'Coverage'
     paths:
       - Coverage.html
       - build/coverage/coverage_report
       - build/coverage/coverage.json
       - build/coverage/coverage.xml
+      - build/coverage/coverage_reports/*.json
     expire_in: 1 week
     reports:
       cobertura: build/coverage/coverage.xml
diff --git a/scripts/cmake/CMakeSetup.cmake b/scripts/cmake/CMakeSetup.cmake
index a549b6247c72f4d76327c5c2b5b5f19832965efe..763b6f4bc0dcec982c889c9a225736ac2853ace4 100644
--- a/scripts/cmake/CMakeSetup.cmake
+++ b/scripts/cmake/CMakeSetup.cmake
@@ -13,7 +13,7 @@ endif()
 CPMAddPackage(
     NAME cmake-modules
     GITHUB_REPOSITORY bilke/cmake-modules
-    GIT_TAG d6d1a778e41cb114e5cdf279b8a659fa0ce9a0d4
+    GIT_TAG d98828f54f6974717798e63195cfbf08fe2daad0
     DOWNLOAD_ONLY YES
 )
 set(CMAKE_MODULE_PATH
diff --git a/scripts/cmake/Coverage.cmake b/scripts/cmake/Coverage.cmake
index 0689aee21cf0f3f94f6842fcd108de3ec4f027ad..0fb66a367f453eda3881fecc93114de26eae18c8 100644
--- a/scripts/cmake/Coverage.cmake
+++ b/scripts/cmake/Coverage.cmake
@@ -38,6 +38,8 @@ endif()
 setup_target_for_coverage_fastcov(
     NAME
     testrunner_coverage
+    BASE_DIRECTORY
+    ${PROJECT_BINARY_DIR}
     EXECUTABLE
     $<TARGET_FILE:testrunner>
     -l
@@ -46,6 +48,7 @@ setup_target_for_coverage_fastcov(
     DEPENDENCIES
     testrunner
     FASTCOV_ARGS
+    --branch-coverage
     --include
     ${PROJECT_SOURCE_DIR}
     ${COVERAGE_ADDITIONAL_ARGS}
@@ -59,6 +62,8 @@ setup_target_for_coverage_fastcov(
 setup_target_for_coverage_fastcov(
     NAME
     ctest_coverage
+    BASE_DIRECTORY
+    ${PROJECT_BINARY_DIR}
     EXECUTABLE
     ctest
     -E
@@ -66,14 +71,27 @@ setup_target_for_coverage_fastcov(
     DEPENDENCIES
     all
     FASTCOV_ARGS
+    --branch-coverage
     --include
     ${PROJECT_SOURCE_DIR}
     ${COVERAGE_ADDITIONAL_ARGS}
     EXCLUDE
     Applications/CLI/
     Tests/
+    POST_CMD
+    perl
+    -i
+    -pe
+    s!${PROJECT_SOURCE_DIR}/!!g
+    ctest_coverage.json
+    NO_DEMANGLE
 )
 
 if(UNIX)
     add_custom_target(clean_coverage find . -name '*.gcda' -delete)
 endif()
+
+configure_file(
+    ${PROJECT_SOURCE_DIR}/scripts/test/generate_coverage_vis_data.in.py
+    ${PROJECT_BINARY_DIR}/generate_coverage_vis_data.py @ONLY
+)
diff --git a/scripts/test/generate_coverage_vis_data.in.py b/scripts/test/generate_coverage_vis_data.in.py
index 649884118d0efc08a3a72857266acba44cd1ac6f..1944db4f2974a5b2c7d318bbafb20308f3bc0513 100755
--- a/scripts/test/generate_coverage_vis_data.in.py
+++ b/scripts/test/generate_coverage_vis_data.in.py
@@ -2,7 +2,9 @@
 
 import os
 
-ctests = ["SurfaceComplexation", "EquilibriumPhase", "KineticReactant"]
+# need to increase OGS_CTEST_MAX_RUNTIME to enable these:
+# ctests = ["SurfaceComplexation", "EquilibriumPhase", "KineticReactant"]
+ctests = ["SteadyState", "ComponentTransport", "ThermoHydroMechanics"]
 report_path = "./coverage_reports"
 
 os.makedirs(report_path, exist_ok=True)