Free marketing tools

Get a practical marketing strategy before you spend another rand.

Generate a 90-day digital marketing plan, check your SEO basics, scan your website content for trust signals, and send us a proper brief when you are ready.

Strategy generator

Free Marketing Strategy Generator

Enter a few details and get a clean, client-ready marketing strategy report. You can download it as Word or PDF.

Your business Ready
Specific inputs create a stronger strategy.
Advanced optional inputs
Stops bots so the tool stays free.
Your report
KPI chart from your inputs

Fill the form and click Generate strategy. Your report appears here.

Free SEO Audit Tool

Enter a page URL and optionally your target keyword. We will scan key on-page SEO signals and show you what to fix first, plus an AI-powered game plan.

Works best on publicly accessible pages. Use it on your own site or client pages.

Free AI Website Content & Authenticity Scanner

Paste your website URL and get an AI-style risk and authenticity report across key pages.

We will crawl a handful of important pages and score them for AI-style clichés, thin content and trust signals.

Send us the details

The better your brief, the sharper our recommendation.

Tell us what is happening, what you want to improve and how soon you want to move. We will come back with a practical next step.

Address2 Sandown Valley Crescent, Sandton

By submitting this form, you agree that The Marketing Specialists may contact you about your enquiry. We do not sell your information.

Digital Marketing FAQs

How long before I start seeing results?

Paid ads can move faster, while SEO and content usually build over months. The right answer depends on your current site, competition and budget.

Do I need SEO for my business?

If people search for what you sell, SEO helps you capture demand without relying only on paid traffic.

What is the best package for me?

The best package depends on your goal, current traffic, conversion rate, budget and urgency. Use the strategy generator or contact form to get a better recommendation.

Can I speak to someone first?

Yes. Send an enquiry, email us, call us or WhatsApp us.

'; } word.addEventListener("click",function(){ const blob=new Blob([wordHtml()],{type:"application/msword"}); const a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download="marketing-strategy-2026.doc"; document.body.appendChild(a); a.click(); setTimeout(()=>{URL.revokeObjectURL(a.href);a.remove();},500); }); pdf.addEventListener("click",async function(){ await html2pdf().set({margin:.4,filename:"marketing-strategy-2026.pdf",image:{type:"jpeg",quality:.95},html2canvas:{scale:2,useCORS:true},jsPDF:{unit:"in",format:"letter",orientation:"portrait"}}).from($("report-shell")).save(); }); function scoreClass(score){ return score>=80?"Strong":score>=50?"Needs work":"High priority"; } function addFix(list, score, label, fix){ list.push({score,label,fix}); } function runSeoAudit(html,url,keyword){ const doc=new DOMParser().parseFromString(html,"text/html"); const title=(doc.querySelector("title")||{}).textContent||""; const desc=(doc.querySelector('meta[name="description"]')||{}).content||""; const h1s=[...doc.querySelectorAll("h1")].map(x=>x.textContent.trim()).filter(Boolean); const h2s=[...doc.querySelectorAll("h2")].length; const imgs=[...doc.querySelectorAll("img")]; const links=[...doc.querySelectorAll("a[href]")]; const words=(doc.body?doc.body.innerText:"").trim().split(/\s+/).filter(Boolean).length; const kw=String(keyword||"").trim().toLowerCase(); const text=(title+" "+desc+" "+(doc.body?doc.body.innerText:"")).toLowerCase(); const fixes=[]; let meta=0, content=0, linksScore=0, tech=0; meta += title.length>=30 && title.length<=65 ? 35 : 15; if(title.length<30||title.length>65) addFix(fixes,30,"Title tag","Rewrite the title tag to roughly 30 to 65 characters."); meta += desc.length>=120 && desc.length<=160 ? 35 : 15; if(desc.length<120||desc.length>170) addFix(fixes,30,"Meta description","Write a clearer meta description around 120 to 160 characters."); meta += h1s.length===1 ? 30 : 10; if(h1s.length!==1) addFix(fixes,25,"H1 structure","Use one clear H1 that matches the page topic."); content += words>=700 ? 35 : words>=350 ? 25 : 10; if(words<500) addFix(fixes,20,"Content depth","Add more useful, specific content to answer buyer questions."); content += h2s>=3 ? 25 : 10; if(h2s<3) addFix(fixes,20,"Subheadings","Break the page into clearer sections with descriptive H2 headings."); content += kw ? (text.includes(kw)?40:10) : 25; if(kw && !text.includes(kw)) addFix(fixes,15,"Target keyword","Use the target keyword naturally in the title, intro, headings and body."); const missingAlt=imgs.filter(i=>!String(i.getAttribute("alt")||"").trim()).length; linksScore += links.length>=5 ? 35 : 15; if(links.length<5) addFix(fixes,20,"Internal links","Add more useful internal links to relevant services, posts or contact pages."); linksScore += imgs.length===0 || missingAlt/imgs.length<=.25 ? 35 : 10; if(missingAlt>0) addFix(fixes,20,"Image alt text","Add descriptive alt text to important images."); linksScore += doc.querySelector('link[rel="canonical"]') ? 30 : 10; if(!doc.querySelector('link[rel="canonical"]')) addFix(fixes,25,"Canonical tag","Add a canonical URL to prevent duplicate-page confusion."); tech += doc.querySelector('meta[name="viewport"]') ? 35 : 5; if(!doc.querySelector('meta[name="viewport"]')) addFix(fixes,30,"Mobile viewport","Add a viewport meta tag for mobile rendering."); tech += html.length<900000 ? 25 : 10; tech += doc.querySelector('script[type="application/ld+json"]') ? 25 : 10; if(!doc.querySelector('script[type="application/ld+json"]')) addFix(fixes,20,"Schema markup","Add relevant JSON-LD schema where useful."); tech += url.startsWith("https://") ? 15 : 5; meta=Math.min(100,meta); content=Math.min(100,content); linksScore=Math.min(100,linksScore); tech=Math.min(100,tech); const overall=Math.round((meta+content+linksScore+tech)/4); return {url,keyword,overall,meta,content,links:linksScore,tech,topFixes:fixes.sort((a,b)=>a.score-b.score).slice(0,5)}; } function renderSeo(audit){ $("seo-score").textContent=audit.overall; $("seo-bar").style.width=audit.overall+"%"; $("seo-summary").textContent=scoreClass(audit.overall)+" SEO foundation. Focus on the quick fixes below first."; $("seo-pills").innerHTML=`Meta: ${audit.meta}/100Content: ${audit.content}/100Links & media: ${audit.links}/100Technical: ${audit.tech}/100`; $("seo-fixes").innerHTML=audit.topFixes.map(f=>`
  • ${esc(f.label)}: ${esc(f.fix)}
  • `).join("") || "
  • No major quick fixes found.
  • "; $("seo-results").classList.remove("hidden"); } $("seo-run").addEventListener("click",async function(){ const raw=$("seo-url").value, kw=$("seo-keyword").value, url=normaliseUrl(raw), btn=$("seo-run"); $("seo-error").classList.add("hidden"); $("seo-results").classList.add("hidden"); $("seo-ai").classList.add("hidden"); if(!url){ $("seo-error").textContent="Please enter a valid URL."; $("seo-error").classList.remove("hidden"); return; } btn.disabled=true; btn.textContent="Running audit..."; try{ const res=await fetch(SEO_PROXY_URL+"?url="+encodeURIComponent(url)); if(!res.ok) throw new Error("Could not fetch page."); const html=await res.text(); const audit=runSeoAudit(html,url,kw); renderSeo(audit); try{ const domain=new URL(url).hostname; const aiRes=await fetch(SEO_AI_URL,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({domain,primaryKeyword:kw,overallScore:audit.overall,technicalScore:audit.tech,contentScore:audit.content,linksScore:audit.links,localScore:0,quickWins:audit.topFixes.map(f=>f.fix),audienceType:"small-business-owner"})}); const ai=await aiRes.json(); if(ai && ai.success && ai.summary){ const s=ai.summary; $("seo-ai-text").textContent=[s.headline,s.executiveSummary,s.topPriorities&&s.topPriorities.join("\n")].filter(Boolean).join("\n\n"); $("seo-ai").classList.remove("hidden"); } }catch(e){} }catch(e){ $("seo-error").textContent="We could not fetch this URL. The site may be blocking bots or unavailable."; $("seo-error").classList.remove("hidden"); }finally{ btn.disabled=false; btn.textContent="Run SEO Audit"; } }); $("asa-run").addEventListener("click",async function(){ const url=normaliseUrl($("asa-url").value), btn=$("asa-run"); $("asa-error").classList.add("hidden"); $("asa-results").classList.add("hidden"); if(!url){ $("asa-error").textContent="Please enter a website URL."; $("asa-error").classList.remove("hidden"); return; } btn.disabled=true; btn.textContent="Running AI audit..."; try{ const res=await fetch(ASA_WORKER_URL+"?url="+encodeURIComponent(url)); if(!res.ok) throw new Error("Worker error"); const data=await res.json(); if(!data || !data.pages || !data.pages.length) throw new Error("No pages analysed."); const ov=data.overview||{}; $("asa-label").textContent="Crawled "+(data.crawledPages||data.pages.length)+" page(s) for "+(data.site||url); $("asa-ai").textContent=(ov.avgAiRisk||0)+"/100"; $("asa-trust").textContent=(ov.avgTrust||0)+"/100"; $("asa-thin").textContent=(ov.avgThinness||0)+"/100"; $("asa-overview").textContent=ov.recommendation || "Here is how your content looks from an authenticity perspective."; $("asa-priorities").innerHTML=(ov.priorityIssues||[]).map(x=>"
  • "+esc(x)+"
  • ").join(""); $("asa-pages").innerHTML=data.pages.map(p=>`${esc(p.title||p.url)}
    ${esc(p.wordCount||0)} words
    ${esc(p.aiRisk)}/100${esc(p.trust)}/100${esc(p.thinness)}/100${(p.flags||[]).map(esc).join(", ")||"—"}`).join(""); $("asa-results").classList.remove("hidden"); }catch(e){ $("asa-error").textContent="Something went wrong while running the audit. Some sites block crawlers. Try a different domain."; $("asa-error").classList.remove("hidden"); }finally{ btn.disabled=false; btn.textContent="Run AI Content Audit"; } }); const contactForm=$("tms-contact-form"), contactStatus=$("contact-status"), contactButton=$("contact-submit"); contactForm.addEventListener("submit",async function(e){ e.preventDefault(); contactButton.disabled=true; contactButton.textContent="Sending..."; contactStatus.className="status"; contactStatus.textContent=""; const data=Object.fromEntries(new FormData(contactForm).entries()); data.source="Free Marketing Strategy page"; try{ const response=await fetch("/api/contact",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(data)}); const result=await response.json().catch(()=>({})); if(!response.ok || !result.ok) throw new Error(result.error || "Something went wrong. Please email info@marketingspecialists.co.za directly."); contactForm.reset(); contactStatus.className="status success"; contactStatus.textContent="Thank you. Your enquiry has been sent. We will get back to you as soon as possible."; }catch(error){ contactStatus.className="status error"; contactStatus.textContent=error.message || "Could not send your enquiry. Please email info@marketingspecialists.co.za directly."; }finally{ contactButton.disabled=false; contactButton.textContent="Send Enquiry"; } }); })();