I don’t see where you are calling campaign_project(). If you need data from a specific project to get the related campaign, calling campaign_project() should be done from within the loop of project_list(). Can there be multiple campaigns for a particular project? If not, running a loop in campaign_project() does not make sense if there is only one campaign to list.
If there is a way to get all campaign data for all projects all at once, the results could be cached and the cache consulted for every project to get its campaign. This would save a whole bunch of API calls.
]]>