أتمتة تقارير الـ “Cannibalization” (تعارض الكلمات المفتاحية)
تُعد مشكلة Keyword Cannibalization من أكثر المشكلات الخفية التي تُضعف أداء المواقع في نتائج البحث. تحدث عندما تتنافس عدة صفحات من نفس الموقع على نفس الاستعلام أو على نية بحث متقاربة، فيرتبك محرك البحث بشأن الصفحة الأجدر بالظهور. النتيجة غالباً تكون تذبذباً في الترتيب، وتوزعاً للنقرات والانطباعات، وانخفاضاً في القدرة على بناء سلطة موضوعية واضحة.
بدلاً من اكتشاف هذه الحالة يدوياً عبر جداول طويلة، يمكن بناء نظام أتمتة يجمع بيانات Google Search Console API، ثم يحلل الاستعلامات والصفحات المتنافسة، ويولد تقريراً قابلاً للتنفيذ. هذا النوع من الأتمتة يمثل امتداداً عملياً لما شرحناه في مدخل إلى عالم أتمتة الـ SEO: لماذا الآن؟، لأنه يحول العمل التحليلي المتكرر إلى عملية منتظمة وموثوقة.
ما المقصود بتعارض الكلمات المفتاحية فعلياً؟
ليس كل ظهور لصفحتين على نفس الكلمة المفتاحية مشكلة. التعارض الحقيقي يظهر عندما تتوزع الإشارات بين صفحات متعددة دون وجود سبب مقصود مثل اختلاف نية البحث أو مرحلة القمع التسويقي. إذا كانت صفحة مقال وصفحة تصنيف وصففحة خدمة تتنافس كلها على الاستعلام نفسه، فقد يفهم محرك البحث أن بنية الموقع غير حاسمة.
لذلك، هدف التقرير الآلي ليس فقط رصد التكرار، بل تصنيفه. نحتاج إلى التفريق بين حالة صحية، مثل تنوع النتائج بين استعلامات فرعية، وحالة ضارة تتطلب دمج المحتوى، أو تحسين الربط الداخلي، أو إعادة ضبط canonical signals، أو إعادة كتابة العناوين.
مصادر البيانات التي يعتمد عليها التقرير
أفضل نقطة انطلاق هي ربط Google Search Console API لاستخراج آلاف الكلمات المفتاحية، لأن بياناته تكشف العلاقة المباشرة بين الاستعلامات والصفحات والانطباعات والنقرات ومتوسط الترتيب. وإذا كنت لا تزال في مرحلة الإعداد، فستحتاج إلى الرجوع إلى التعامل مع Google Cloud Console وإنشاء مفاتيح الـ API مع تهيئة بيئة العمل: تثبيت Python والمكتبات الأساسية.
عادةً نطلب البيانات حسب البعدين query وpage خلال آخر 90 يوماً أو 180 يوماً. هذه المدة تقلل ضوضاء التقلبات اليومية وتمنحنا إشارات أقرب للواقع. ويمكن لاحقاً تخزين النتائج بصيغة JSON أو في جداول تحليلية، وهو ما يرتبط مباشرة بمقال أساسيات التعامل مع ملفات JSON (لغة التفاهم بين الأنظمة).
منطق كشف التعارض: كيف يعرف السكربت أن هناك مشكلة؟
المنهج العملي يقوم على تجميع الصفوف حسب الاستعلام، ثم فحص عدد الصفحات المختلفة التي ظهرت على هذا الاستعلام. إذا وجدنا أكثر من صفحة واحدة، ننتقل إلى طبقة تقييم ثانية بدلاً من إطلاق حكم فوري. هذه الطبقة تمنع الإيجابيات الكاذبة.
المعايير الأكثر فاعلية
- وجود استعلام واحد مرتبط بصفحتين أو أكثر.
- أن تحصل كل صفحة على حد أدنى من الانطباعات، مثلاً
10 impressionsأو أكثر. - تقارب متوسط الترتيب بين الصفحات، بما يشير إلى تنافس فعلي.
- تقارب الموضوع أو النية بعد تحليل
slugوالعنوان أو تصنيف الصفحة. - وجود تذبذب زمني بين صفحتين على نفس الاستعلام عند تتبع الفترات المختلفة.
هذا التصميم قريب من منطق البرمجة المعتمد على المهام (Task-Oriented Programming)، لأننا نقسم العملية إلى مهام: جمع البيانات، تنظيفها، كشف الأنماط، ثم اقتراح الإجراء المناسب.
بناء سكربت Python لتوليد التقرير
في التطبيق العملي، يمكن استخدام مكتبات مثل pandas وgoogleapiclient. ويجب حفظ المفاتيح والملفات الحساسة خارج الكود كما أوضحنا في الحماية والأمان: كيف تخفي مفاتيحك السرية في الكود؟.
import pandas as pd
def find_cannibalization(df, min_impressions=10, min_pages=2):
required_cols = ["query", "page", "clicks", "impressions", "position"]
for col in required_cols:
if col not in df.columns:
raise ValueError(f"Missing required column: {col}")
filtered = df[df["impressions"] >= min_impressions].copy()
grouped = (
filtered.groupby("query")
.agg(
pages=("page", "nunique"),
total_clicks=("clicks", "sum"),
total_impressions=("impressions", "sum")
)
.reset_index()
)
target_queries = grouped[grouped["pages"] >= min_pages]["query"]
candidates = filtered[filtered["query"].isin(target_queries)].copy()
detail = (
candidates.groupby(["query", "page"])
.agg(
clicks=("clicks", "sum"),
impressions=("impressions", "sum"),
avg_position=("position", "mean")
)
.reset_index()
.sort_values(["query", "impressions"], ascending=[True, False])
)
summary_rows = []
for query, group in detail.groupby("query"):
top_pages = group["page"].tolist()
summary_rows.append({
"query": query,
"competing_pages": len(top_pages),
"primary_page": top_pages[0],
"secondary_pages": " | ".join(top_pages[1:]),
"total_impressions": group["impressions"].sum(),
"position_gap": round(group["avg_position"].max() - group["avg_position"].min(), 2)
})
summary = pd.DataFrame(summary_rows)
return summary, detail
# Example usage:
# df = pd.read_csv("gsc_query_page_export.csv")
# summary, detail = find_cannibalization(df)
# summary.to_csv("cannibalization_summary.csv", index=False)
# detail.to_csv("cannibalization_detail.csv", index=False)
هذا السكربت لا يقرر الحل النهائي، لكنه ينجز أهم مرحلة: تحويل البيانات الخام إلى قائمة استعلامات تحتاج تدخلاً تحريرياً أو هيكلياً. بعدها يمكن إضافة عمود قرار مثل merge أو keep_separate أو reoptimize_internal_links.
أتمتة الإخراج إلى Google Sheets ولوحة عمل قابلة للتنفيذ
إذا كان فريق التحرير يعمل على الجداول، فمن المفيد إرسال النتائج إلى Google Sheets. هنا تظهر قيمة مقدمة في Google Apps Script لغير المبرمجين وكيفية ربط Google Sheets بالعالم الخارجي عبر Script. الفكرة هي جعل الجدول ليس مجرد مخرجات، بل مساحة عمل يتابع فيها الفريق حالة كل تعارض.
- عمود للاستعلام الرئيسي.
- عمود للصفحة المرشحة كصفحة أساسية.
- عمود للصفحات المتنافسة.
- عمود لنوع الإجراء المقترح.
- عمود لحالة التنفيذ:
PendingأوDone.
كما يمكن جدولة السكربت أسبوعياً، ثم مقارنة النتائج زمنياً لاكتشاف ما إذا كانت المشكلة تتكرر أو تتحسن بعد التعديل. هذا يحول التقرير من أداة تشخيص إلى نظام مراقبة مستمر.
كيف نفسر النتائج بشكل صحيح؟
أخطر خطأ هو اعتبار كل تعارض إشارة لدمج المقالات. أحياناً تكون الصفحات المختلفة تخدم نوايا متعددة، أو تستهدف مراحل مختلفة من قرار المستخدم. لذلك، التقرير يجب أن يدعم القرار البشري لا أن يستبدله.
أهم الإجراءات التصحيحية
- دمج الصفحات المتشابهة جداً في صفحة واحدة أقوى.
- إعادة صياغة
titleوH1لتوضيح الزاوية المختلفة لكل صفحة. - تحسين الربط الداخلي لتوجيه السلطة إلى الصفحة الأساسية.
- إزالة التخفيف غير المقصود الناتج عن تكرار التغطية الموضوعية.
- مراجعة بنية التصنيفات والوسوم إذا كانت تولد صفحات ضعيفة تتنافس مع المقالات.
عند مراجعة أي حالة
Cannibalization، اسأل أولاً: هل الصفحتان تخدمان النية نفسها؟ إذا كانت الإجابة نعم، فالأولوية غالباً للتوحيد أو إعادة التمركز. وإذا كانت الإجابة لا، فالأولوية لتوضيح الفروق الدلالية والبنيوية لمحرك البحث.
رفع جودة التقرير ليتوافق مع معايير المحتوى الحديثة
من منظور EEAT، القيمة الحقيقية ليست في عرض قائمة مشكلات فقط، بل في تقديم تفسير عملي مدعوم بمنهج واضح. التقرير الجيد يجب أن يربط بين البيانات، والنية البحثية، وبنية المحتوى، والإجراء المقترح. هذا ما يجعله مفيداً للمحرر وصاحب الموقع، وليس مجرد تصدير آلي لأرقام.
كما أن تنظيم العملية من خلال مفهوم الـ API: كيف نطلب البيانات من Google وOpenAI يساعد لاحقاً على توسيع المشروع. يمكن مثلاً استخدام نماذج الذكاء الاصطناعي لتلخيص الفرق بين الصفحات المتنافسة، أو اقتراح زاوية تحريرية لكل صفحة، بشرط أن يبقى القرار النهائي خاضعاً للمراجعة البشرية.
الخلاصة
أتمتة تقارير Cannibalization ليست رفاهية، بل خطوة ناضجة في إدارة المحتوى على المواقع التي تتوسع باستمرار. حين تجمع بيانات Search Console، وتطبق قواعد كشف ذكية، ثم تُخرج النتائج إلى لوحة عمل قابلة للتنفيذ، فإنك تقلل التشتت التحريري وترفع وضوح الإشارات لمحركات البحث.
النتيجة النهائية ليست فقط تحسين ترتيب كلمة مفتاحية واحدة، بل بناء أرشيف محتوى أكثر تماسكاً، وأسهل في الإدارة، وأكثر قابلية للنمو العضوي طويل المدى. وهذه هي القوة الحقيقية للأتمتة عندما تُبنى على فهم تقني سليم لا على تكرار ميكانيكي للمهام.
4 comments