you need to put the other join conditions into their respective ON clauses as well
here's your re-written query...
SELECT SUM( op.products_quantity ) AS num_sold
, SUM( op.final_price * op.products_quantity ) AS total_sales
FROM orders as o
JOIN orders_products AS op
ON op.orders_id = o.orders_id
JOIN products AS p
ON p.products_id = op.products_id
JOIN products_description AS pd
ON pd.products_id = p.products_id
JOIN ( SELECT products_id
, COUNT(*) AS visits
WHERE timestamp BETWEEN '".$start_date."'
BY products_id ) AS visits
ON visits.products_id = p.products_id
WHERE o.date_purchased BETWEEN '".$start_date."'
BY total_sales DESC
note carefully the sequence of tables in the FROM clause, and notice that the only WHERE condition applies to the first table mentioned in the FROM clause -- in effect, this is what "drives" the query, i.e. this is the most restricted table so i always write it first, so that the other tables are joined only to the rows you're interested in
the way you had it, with unqualified joins missing their ON conditions, you'd get a humoungous cross join, after which the various conditions in your WHERE clause would start throwing most joined rows away