Using Salesforce Apex, establishing a relationship between leads and campaigns should be as simple as setting the campaign id on a standard field on the lead.  After all, if you take a look at a lead’s detail page, the lead has a lookup to campaigns.  Unfortunately, establishing that relationship is a bit convoluted.

The relationship is actually dictated by a campaign member object.  The campaign member object is a junction with a many-to-many relationship between leads and campaigns (or contacts and campaigns).  Once the lead is created, to add it to a campaign, a campaign member object must be created linking the lead to its campaign.  This campaign member then complicates any workflow centered around leads and campaigns. 

Recently, Cloud Craze had a requirement to send workflow e-mail when a lead is created and assigned to a given campaign.  The workflow should fire when a lead’s campaign name is set to a certain value.  After creating the workflow on the lead object, the workflow doesn’t fire as desired.  The issue stems from creating the lead, and creating the campaign member afterward.  Regardless of specifying the ‘When a record is created, or when a record is edited and did not previously meet the rule criteria’ option,  the workflow will not fire until any of the lead fields are updated.  In other words, modifying the campaign member or campaign object has no effect on updating the lead and firing the workflow.

There are actually two solutions to get this particular workflow requirement to work.  One is to create/modify a trigger (or use another workflow rule for field update) to update the lead when the campaign member is added.  This solution is dodgy at best, and results in extra DML transaction(s).

The second solution is to create the workflow on the campaign member junction instead of the lead.  When the junction is created correctly, it has access to both lead and campaign fields.  The workflow can traverse both the lead and the campaign for the desired criteria and then fire.  There may be some issues with this scenario if the workflow needs to fire when lead or campaign fields are updated, but for sending an e-mail when the lead is first assigned to a campaign, this solution works very well.