It is impossible to give detailed advice on a query that we only see fragments off.
But, generally, when you have many CTEs, it can sometimes help if you materialise some intermediate CTE into a temp table, and then work from there.
When you have complex queries, the optimizer can easily go wrong. When you stick in a temp table with statistics, the optimizer has more information for the rest of the steps. Watch out that this cuts both ways. The CTEs are logical building blocks, and not necessarily computed as such, and the optimizer may recast the computation order. So if you have a temp table in the wrong place, execution time can increase.
If you are referring to the same CTE multiple times in a query, that is definitely a good candidate for a temp table, because SQL Server will expand the definition of the CTE for every occurrence, so there will be double work, one way or another.